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   100120 use strict;
  21         39  
  21         711  
4 21     21   110 use warnings;
  21         43  
  21         523  
5              
6 21     21   120 use File::Basename ();
  21         35  
  21         302  
7 21     21   100 use File::Path ();
  21         35  
  21         339  
8              
9 21     21   10910 use ExtUtils::XSpp::Parser;
  21         70  
  21         22636  
10              
11             sub new {
12 85     85 0 2843 my( $class, %args ) = @_;
13 85         283 my $self = bless \%args, $class;
14              
15 85         251 return $self;
16             }
17              
18             sub generate {
19 85     85 0 535 my( $self ) = @_;
20              
21 85         392 foreach my $typemap ( $self->typemaps ) {
22 1         14 ExtUtils::XSpp::Parser->new( file => $typemap )->parse;
23             }
24              
25 85         443 my $parser = ExtUtils::XSpp::Parser->new( file => $self->file,
26             string => $self->string,
27             );
28 85         438 my $success = $parser->parse;
29 85 50       305 return() if not $success;
30 85         6564 my $generated = $self->_emit( $parser );
31              
32 85         609 my $typemap_code = ExtUtils::XSpp::Typemap::get_xs_typemap_code_for_all_typemaps();
33 85 100 66     359 if (defined $typemap_code && $typemap_code =~ /\S/) {
34 3 50 33     19 if (exists $generated->{'-'} and $generated->{'-'} ne '') {
    0          
35 3         23 $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         49307 return $generated;
46             }
47              
48             sub process {
49 1     1 0 1747 my( $self ) = @_;
50              
51 1         6 my $generated = $self->generate;
52 1 50       7 return () if not $generated;
53 1         8 return $self->_write( $generated );
54             }
55              
56             sub _write {
57 1     1   4 my( $self, $out ) = @_;
58              
59 1         6 foreach my $f ( keys %$out ) {
60 2 100       10 if( $f eq '-' ) {
61 1 50       6 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       11 print $$out{$f} or die "Error writing output";
76             }
77             } else {
78 1         132 File::Path::mkpath( File::Basename::dirname( $f ) );
79              
80 1 50       154 open my $fh, '>', $f or die "open '$f': $!";
81 1         4 binmode $fh;
82 1 50       61 print $fh $$out{$f} or die "Error writing to '$f': $!";
83 1 50       81 close $fh or die "close '$f': $!";
84             }
85             }
86              
87 1         7 return 1;
88             }
89              
90             sub _emit {
91 85     85   169 my( $self, $parser ) = @_;
92 85         412 my $data = $parser->get_data;
93 85         144 my %out;
94 85         184 my $out_file = '-';
95 85         304 my %state = ( current_module => undef );
96              
97 85         148 foreach my $plugin ( @{$parser->post_process_plugins} ) {
  85         370  
98 4         8 my $method = $plugin->{method};
99              
100 4         21 $plugin->{plugin}->$method( $data );
101             }
102              
103 85         352 $out{'-'} = preamble();
104 85         207 foreach my $e ( @$data ) {
105 264 100       2364 if( $e->isa( 'ExtUtils::XSpp::Node::Module' ) ) {
106 82         166 $state{current_module} = $e;
107             }
108 264 100       1767 if( $e->isa( 'ExtUtils::XSpp::Node::File' ) ) {
109 8         31 $out_file = $e->file;
110 8   66     53 $out{$out_file} ||= preamble();
111             }
112 264         1370 $out{$out_file} .= $e->print( \%state );
113             }
114              
115 85         339 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 352 }
127              
128 85 100   85 0 140 sub typemaps { @{$_[0]->{typemaps} || []} }
  85         7962  
129 85     85 0 413 sub file { $_[0]->{file} }
130 85     85 0 905 sub string { $_[0]->{string} }
131 0     0 0 0 sub output { $_[0]->{output} }
132 1     1 0 5 sub xsubpp { $_[0]->{xsubpp} }
133 0     0 0   sub xsubpp_args { $_[0]->{xsubpp_args} }
134              
135             1;