File Coverage

blib/lib/ExtUtils/XSpp/Driver.pm
Criterion Covered Total %
statement 69 81 85.1
branch 18 34 52.9
condition 5 15 33.3
subroutine 15 17 88.2
pod 0 10 0.0
total 107 157 68.1


line stmt bran cond sub pod time code
1             package ExtUtils::XSpp::Driver;
2              
3 21     21   112266 use strict;
  21         29  
  21         599  
4 21     21   65 use warnings;
  21         27  
  21         631  
5              
6 21     21   81 use File::Basename ();
  21         29  
  21         207  
7 21     21   66 use File::Path ();
  21         26  
  21         432  
8              
9 21     21   8006 use ExtUtils::XSpp::Parser;
  21         61  
  21         17447  
10              
11             sub new {
12 85     85 0 186159 my( $class, %args ) = @_;
13 85         164 my $self = bless \%args, $class;
14              
15 85         164 return $self;
16             }
17              
18             sub generate {
19 85     85 0 326 my( $self ) = @_;
20              
21 85         218 foreach my $typemap ( $self->typemaps ) {
22 1         8 ExtUtils::XSpp::Parser->new( file => $typemap )->parse;
23             }
24              
25 85         214 my $parser = ExtUtils::XSpp::Parser->new( file => $self->file,
26             string => $self->string,
27             );
28 85         287 my $success = $parser->parse;
29 85 50       185 return() if not $success;
30 85         271 my $generated = $self->_emit( $parser );
31              
32 85         301 my $typemap_code = ExtUtils::XSpp::Typemap::get_xs_typemap_code_for_all_typemaps();
33 85 100 66     230 if (defined $typemap_code && $typemap_code =~ /\S/) {
34 3 50 33     18 if (exists $generated->{'-'} and $generated->{'-'} ne '') {
    0          
35 3         15 $generated->{'-'} = $typemap_code . $generated->{'-'};
36             }
37             elsif (my @files = grep !/^-$/, keys %$generated) {
38 0   0     0 $generated->{$files[0]} = $typemap_code . ($generated->{$files[0]}||'');
39             }
40             else {
41 0   0     0 $generated->{'-'} = $typemap_code . ($generated->{'-'}||'');
42             }
43             }
44              
45 85         25083 return $generated;
46             }
47              
48             sub process {
49 1     1 0 26 my( $self ) = @_;
50              
51 1         3 my $generated = $self->generate;
52 1 50       5 return () if not $generated;
53 1         5 return $self->_write( $generated );
54             }
55              
56             sub _write {
57 1     1   3 my( $self, $out ) = @_;
58              
59 1         4 foreach my $f ( keys %$out ) {
60 2 100       9 if( $f eq '-' ) {
61 1 50       5 if( $self->xsubpp ) {
62 0         0 require IPC::Open2;
63              
64 0   0     0 my $cmd = $self->xsubpp . ' ' . ( $self->xsubpp_args || '' )
65             . ' -';
66 0         0 my $pid = IPC::Open2::open2( '>&STDOUT', my $fh, $cmd );
67              
68 0 0       0 print $fh $$out{$f} or die "Error writing to xsubpp: $!";
69 0 0       0 close $fh or die "Error writing to xsubpp: $!";
70 0         0 waitpid( $pid, 0 );
71 0         0 my $exit_code = $? >> 8;
72              
73 0 0       0 return 0 if $exit_code;
74             } else {
75 1 50       6 print $$out{$f} or die "Error writing output";
76             }
77             } else {
78 1         112 File::Path::mkpath( File::Basename::dirname( $f ) );
79              
80 1 50       238 open my $fh, '>', $f or die "open '$f': $!";
81 1         7 binmode $fh;
82 1 50       50 print $fh $$out{$f} or die "Error writing to '$f': $!";
83 1 50       66 close $fh or die "close '$f': $!";
84             }
85             }
86              
87 1         7 return 1;
88             }
89              
90             sub _emit {
91 85     85   159 my( $self, $parser ) = @_;
92 85         270 my $data = $parser->get_data;
93 85         116 my %out;
94 85         119 my $out_file = '-';
95 85         267 my %state = ( current_module => undef );
96              
97 85         125 foreach my $plugin ( @{$parser->post_process_plugins} ) {
  85         219  
98 4         7 my $method = $plugin->{method};
99              
100 4         12 $plugin->{plugin}->$method( $data );
101             }
102              
103 85         213 $out{'-'} = preamble();
104 85         167 foreach my $e ( @$data ) {
105 264 100       946 if( $e->isa( 'ExtUtils::XSpp::Node::Module' ) ) {
106 82         170 $state{current_module} = $e;
107             }
108 264 100       881 if( $e->isa( 'ExtUtils::XSpp::Node::File' ) ) {
109 8         21 $out_file = $e->file;
110 8   66     30 $out{$out_file} ||= preamble();
111             }
112 264         839 $out{$out_file} .= $e->print( \%state );
113             }
114              
115 85         242 return \%out;
116             }
117              
118             sub preamble {
119             return <
120             #include
121             #undef xsp_constructor_class
122             #define xsp_constructor_class(c) (c)
123              
124              
125             EOT
126 89     89 0 220 }
127              
128 85 100   85 0 121 sub typemaps { @{$_[0]->{typemaps} || []} }
  85         397  
129 85     85 0 210 sub file { $_[0]->{file} }
130 85     85 0 496 sub string { $_[0]->{string} }
131 0     0 0 0 sub output { $_[0]->{output} }
132 1     1 0 40 sub xsubpp { $_[0]->{xsubpp} }
133 0     0 0   sub xsubpp_args { $_[0]->{xsubpp_args} }
134              
135             1;