File Coverage

blib/lib/Inline/Filters.pm
Criterion Covered Total %
statement 68 85 80.0
branch 13 20 65.0
condition 5 11 45.4
subroutine 11 14 78.5
pod 9 9 100.0
total 106 139 76.2


line stmt bran cond sub pod time code
1             package Inline::Filters;
2 3     3   143322 use strict;
  3         5  
  3         69  
3 3     3   10 use Config;
  3         4  
  3         147  
4             our $VERSION = "0.20";
5 3     3   11 use File::Spec;
  3         9  
  3         3268  
6            
7             #============================================================================
8             # Object Interface
9             #============================================================================
10             sub new {
11 4     4 1 39 my $class = shift;
12 4         11 return bless { filter => shift, coderef => shift }, $class;
13             }
14              
15             sub filter {
16 4     4 1 13433 my ($self, $o, $code) = @_;
17 4         17 return $self->{coderef}->($o, $code);
18             }
19              
20             #============================================================================
21             # Strip POD
22             #============================================================================
23             sub Strip_POD {
24 2     2 1 3 my $ilsm = shift;
25 2         1 my $code = shift;
26 2         22 $code =~ s/^=\w+[^\n]*\n\n(.*?)(^=cut\n\n|\Z)//gsm;
27 2         6 return $code;
28             }
29              
30             #============================================================================
31             # Strip comments in various languages
32             #============================================================================
33             sub _skip_quoted {
34 4     4   5 my ($text, $index, $closer) = @_;
35 4         7 for (my $i=$index+1; $i
36 80         54 my $p = substr($text, $i-1, 1);
37 80         51 my $c = substr($text, $i, length($closer));
38 80 50 33     136 return $i if ($c eq $closer and ($p ne '\\' or length($closer)>1));
      66        
39             }
40 0         0 return $index; # must not have been a string
41             }
42              
43             sub _strip_comments {
44 2     2   3 my ($txt, $opn, $cls, @quotes) = @_;
45 2         2 my $i = -1;
46 2         4 while (++$i < length $txt) {
47 359         189 my $closer;
48 359 100       235 if (grep {my $r=substr($txt,$i,length($_)) eq $_; $closer=$_ if $r; $r}
  359 100       269  
  359         362  
  359         497  
49             @quotes) {
50 4         5 $i = _skip_quoted($txt, $i, $closer);
51 4         5 next;
52             }
53 355 100       646 if (substr($txt, $i, length($opn)) eq $opn) {
54 3         4 my $e = index($txt, $cls, $i) + length($cls);
55 3         28 substr($txt, $i, $e-$i) =~ s/[^\n]/ /g;
56 3         3 $i--;
57 3         6 next;
58             }
59             }
60 2         3 return $txt;
61             }
62              
63             # Note: strips both C and C++ comments because so many compilers accept
64             # both styles for C programs. Perhaps a --strict parameter?
65             sub Strip_C_Comments {
66 1     1 1 1 my $ilsm = shift;
67 1         2 my $code = shift;
68 1         1 $code = _strip_comments($code, '//', "\n", '"');
69 1         2 $code = _strip_comments($code, '/*', '*/', '"');
70 1         4 return $code;
71             }
72              
73             sub Strip_CPP_Comments {
74 0     0 1 0 my $ilsm = shift;
75 0         0 my $code = shift;
76 0         0 $code = _strip_comments($code, '//', "\n", '"');
77 0         0 $code = _strip_comments($code, '/*', '*/', '"');
78 0         0 return $code;
79             }
80              
81             sub Strip_Python_Comments {
82 0     0 1 0 my $ilsm = shift;
83 0         0 my $code = shift;
84 0         0 $code = _strip_comments($code, '#', "\n", '"', '"""', '\'');
85 0         0 return $code;
86             }
87              
88             sub Strip_TCL_Comments {
89 0     0 1 0 my $ilsm = shift;
90 0         0 my $code = shift;
91              
92 0         0 return $code;
93             }
94              
95             #============================================================================
96             # Preprocess C and C++
97             #============================================================================
98             sub Preprocess {
99 1     1 1 2 my $ilsm = shift;
100 1         0 my $code = shift;
101              
102 1         1 my @inc_array;
103 1 50       3 if (defined($ilsm->{ILSM}{MAKEFILE}{INC})) {
104 1 50       1 if (ref($ilsm->{ILSM}{MAKEFILE}{INC} eq 'ARRAY')) {
105 0         0 @inc_array = @{$ilsm->{ILSM}{MAKEFILE}{INC}};
  0         0  
106             }
107             else {
108 1         2 @inc_array = ($ilsm->{ILSM}{MAKEFILE}{INC});
109             }
110             }
111             else {
112 0         0 @inc_array = ();
113             }
114              
115 1         1 my $cppflags = q{};
116 1 50       3 if (defined $ilsm->{CONFIG}->{CPPFLAGS}) {
117 0         0 $cppflags = $ilsm->{CONFIG}->{CPPFLAGS};
118             }
119             my $cpp = join ' ', ($Config{cpprun},
120             $Config{cppflags},
121 1         44 $cppflags,
122             "-I$Config{archlibexp}/CORE",
123             @inc_array
124             );
125              
126 1         18 my $tmpfile = File::Spec->catfile($ilsm->{API}{build_dir}, "Filters$$.c");
127 1         3 $ilsm->mkpath($ilsm->{API}{build_dir});
128 1         118 my ($CSRC, $PROCESSED);
129 1 50       59 open $CSRC, ">", $tmpfile or die $!;
130 1         5 print $CSRC $code;
131 1         33 close $CSRC;
132 1 50       1334 open $PROCESSED, "$cpp \"$tmpfile\" |" or die $!;
133 1         7101 $code = join '', <$PROCESSED>;
134 1         23 close $PROCESSED;
135              
136             # default yes, will remove Filters*.c files, this is the same config option used by Inline::C(PP);
137             # must disable when using gdb to debug Inline::C(PP) code
138 1 50 33     61 if ((not defined $ilsm->{CONFIG}->{CLEAN_AFTER_BUILD}) or $ilsm->{CONFIG}->{CLEAN_AFTER_BUILD}) {
139 1         113 unlink $tmpfile;
140             }
141              
142 1         33 return $code;
143             }
144              
145             #============================================================================
146             # Returns a list of key, value pairs; a filter and its code reference.
147             #============================================================================
148             my %filters =
149             (
150             ALL => [
151             Strip_POD => \&Strip_POD,
152             Preprocess => \&Preprocess,
153             ],
154             C => [
155             Strip_Comments => \&Strip_C_Comments,
156             ],
157             CPP => [
158             Strip_Comments => \&Strip_CPP_Comments,
159             ],
160             JAVA => [
161             Strip_Comments => \&Strip_CPP_Comments,
162             ],
163             );
164              
165             sub get_filters {
166 3     3 1 21 my $language = shift;
167 3         6 my ($all, $lang) = @filters{ALL => $language};
168 3   50     12 $lang ||= [];
169 3         11 return (@$all, @$lang);
170             }
171              
172             1;