File Coverage

blib/lib/ExtUtils/XSBuilder/FunctionMap.pm
Criterion Covered Total %
statement 12 127 9.4
branch 0 48 0.0
condition 0 25 0.0
subroutine 4 18 22.2
pod 0 14 0.0
total 16 232 6.9


line stmt bran cond sub pod time code
1             package ExtUtils::XSBuilder::FunctionMap;
2              
3 1     1   6 use strict;
  1         1  
  1         35  
4 1     1   5 use warnings FATAL => 'all';
  1         1  
  1         33  
5 1     1   723 use ExtUtils::XSBuilder::MapUtil qw(function_table structure_table);
  1         3  
  1         82  
6 1     1   6 use Data::Dumper ;
  1         2  
  1         1915  
7              
8             our @ISA = qw(ExtUtils::XSBuilder::MapBase);
9              
10             sub new {
11 0     0 0   my $class = shift;
12 0           bless {wrapxs => shift}, $class;
13             }
14              
15             #for adding to function.map
16             sub generate {
17 0     0 0   my $self = shift;
18              
19 0           my $missing = $self->check;
20 0 0         return unless $missing;
21              
22 0           print " $_\n" for @$missing;
23             }
24              
25 0     0 0   sub disabled { shift->{disabled} }
26              
27             #look for functions that do not exist in *.map
28             sub check {
29 0     0 0   my $self = shift;
30 0           my $map = $self->get;
31              
32 0           my @missing;
33 0           my $parsesource = $self -> {wrapxs} -> parsesource_objects ;
34              
35 0           loop:
36 0           for my $name (map $_->{name}, @{ function_table($self -> {wrapxs}) }) {
37 0 0         next if exists $map->{$name};
38             #foreach my $obj (@$parsesource)
39             # {
40             # next loop if ($obj -> handle_func ($name)) ;
41             # }
42 0           push @missing, $name ;
43             }
44              
45 0 0         return @missing ? \@missing : undef;
46             }
47              
48             #look for functions in *.map that do not exist
49             my $special_name = qr{(^DEFINE_|DESTROY$)};
50              
51             sub check_exists {
52 0     0 0   my $self = shift;
53              
54 0           my %functions = map { $_->{name}, 1 } @{ function_table($self -> {wrapxs}) };
  0            
  0            
55 0           my @missing = ();
56              
57 0           for my $name (keys %{ $self->{map} }) {
  0            
58 0 0         next if $functions{$name};
59 0 0         push @missing, $name unless $name =~ $special_name;
60             }
61              
62 0 0         return @missing ? \@missing : undef;
63             }
64              
65             my $keywords = join '|', qw(MODULE PACKAGE PREFIX BOOT);
66              
67              
68              
69             sub class_c_prefix {
70 0     0 0   my $self = shift;
71 0           my $class = shift;
72 0           $class =~ s/:/_/g;
73 0           $class;
74             }
75              
76             sub class_xs_prefix {
77 0     0 0   my $self = shift;
78 0           my $class = shift;
79 0           my $class_prefix = $self -> class_c_prefix($class);
80 0           return $self -> {wrapxs} -> my_xs_prefix . $class_prefix . '_' ;
81             }
82              
83             sub needs_prefix {
84 0     0 0   my $self = shift;
85 0           my $name = shift;
86 0           $self -> {wrapxs} -> needs_prefix ($name) ;
87             }
88              
89             sub make_prefix {
90 0     0 0   my($self, $name, $class) = @_;
91 0           my $class_prefix = $self -> class_xs_prefix($class);
92 0 0         return $name if $name =~ /^$class_prefix/;
93 0           $class_prefix . $name;
94             }
95              
96              
97             sub guess_prefix {
98 0     0 0   my $self = shift;
99 0           my $entry = shift;
100              
101 0           my($name, $class) = ($entry->{name}, $entry->{class});
102 0           my $prefix = "";
103 0           my $myprefix = $self -> {wrapxs} -> my_xs_prefix ;
104 0           $name =~ s/^DEFINE_//;
105 0           $name =~ s/^$myprefix//i;
106              
107 0   0       (my $guess = lc($entry->{class} || $entry->{module}) . '_') =~ s/::/_/g;
108 0           $guess =~ s/(apache)_/($1|ap)_{1,2}/;
109              
110 0 0         if ($name =~ s/^($guess).*/$1/i) {
111 0           $prefix = $1;
112             }
113             else {
114 0 0         if ($name =~ /^(apr?_)/) {
115 0           $prefix = $1;
116             }
117             }
118              
119             #print "GUESS prefix=$guess, name=$entry->{name} -> $prefix\n";
120              
121 0           return $prefix;
122             }
123              
124             sub parse {
125 0     0 0   my($self, $fh, $map) = @_;
126 0           my %cur;
127 0           my $disabled = 0;
128              
129 0           while ($fh->readline) {
130 0 0         if (/($keywords)=/o) {
131 0           $disabled = s/^\W//; #module is disabled
132 0           my %words = $self->parse_keywords($_);
133              
134 0 0         if ($words{MODULE}) {
135 0           %cur = ();
136             }
137              
138 0 0         if ($words{PACKAGE}) {
139 0           delete $cur{CLASS};
140             }
141              
142 0           for (keys %words) {
143 0           $cur{$_} = $words{$_};
144             }
145              
146 0           next;
147             }
148              
149 0           my($name, $dispatch, $argspec, $alias) = split /\s*\|\s*/;
150              
151 0           my $dispatch_argspec = '' ;
152              
153 0 0 0       if ($dispatch && ($dispatch =~ m#\s*(.*?)\s*\((.*)\)#))
154             {
155 0           $dispatch = $1;
156 0           $dispatch_argspec = $2;
157             }
158              
159 0           my $return_type;
160              
161 0 0         if ($name =~ s/^([^:]+)://) {
162 0           $return_type = $1;
163             }
164              
165 0 0 0       if ($name =~ s/^(\W)// or not $cur{MODULE} or $disabled) {
      0        
166             #notimplemented or cooked by hand
167 0           $map->{$name} = undef;
168 0   0       push @{ $self->{disabled}->{ $1 || '!' } }, $name;
  0            
169 0           next;
170             }
171              
172 0 0         if (my $package = $cur{PACKAGE}) {
173 0 0         unless ($package eq 'guess') {
174 0           $cur{CLASS} = $package;
175             }
176 0 0         if ($cur{ISA}) {
177 0           $self->{isa}->{ $cur{MODULE} }->{$package} = delete $cur{ISA};
178             }
179 0 0         if ($cur{BOOT}) {
180 0           $self->{boot}->{ $cur{MODULE} } = delete $cur{BOOT};
181             }
182             }
183             else {
184 0           $cur{CLASS} = $cur{MODULE};
185             }
186              
187 0 0 0       if ($name =~ /^DEFINE_/ and $cur{CLASS}) {
188 0           $name =~ s{^(DEFINE_)(.*)}
189 0           {$1 . $self->make_prefix($2, $cur{CLASS})}e;
190 0           print "DEFINE $name arg=$argspec\n" ;
191             }
192              
193 0 0 0       my $entry = $map->{$name} = {
194             name => $alias || $name,
195             dispatch => $dispatch,
196             dispatch_argspec => $dispatch_argspec,
197             argspec => $argspec ? [split /\s*,\s*/, $argspec] : "",
198             return_type => $return_type,
199             alias => $alias,
200             };
201              
202 0           for (keys %cur) {
203 0           $entry->{lc $_} = $cur{$_};
204             }
205              
206             #avoid 'use of uninitialized value' warnings
207 0   0       $entry->{$_} ||= "" for keys %{ $entry };
  0            
208 0 0         if ($entry->{dispatch} =~ /_$/) {
209 0           $entry->{dispatch} .= $name;
210             }
211             }
212             }
213              
214             sub get {
215 0     0 0   my $self = shift;
216              
217 0   0       $self->{map} ||= $self->parse_map_files;
218             }
219              
220             sub prefixes {
221 0     0 0   my $self = shift;
222 0 0         $self = ExtUtils::XSBuilder::FunctionMap->new unless ref $self;
223              
224 0           my $map = $self->get;
225 0           my %prefix;
226              
227 0           while (my($name, $ent) = each %$map) {
228 0 0         next unless $ent->{prefix};
229 0           $prefix{ $ent->{prefix} }++;
230             }
231              
232 0           $prefix{$_} = 1 for qw(ap_ apr_); #make sure we get these
233              
234 0           [keys %prefix]
235             }
236              
237              
238             sub write {
239 0     0 0   my ($self, $fh, $newentries, $prefix) = @_ ;
240              
241 0           foreach (@$newentries)
242             {
243 0           $fh -> print ($prefix, $self -> {wrapxs} -> mapline_func ($_), "\n") ;
244             }
245             }
246              
247             1;
248             __END__