File Coverage

blib/lib/Inline/Filters.pm
Criterion Covered Total %
statement 67 84 79.7
branch 12 18 66.6
condition 4 8 50.0
subroutine 11 14 78.5
pod 9 9 100.0
total 103 133 77.4


line stmt bran cond sub pod time code
1             package Inline::Filters;
2 3     3   150178 use strict;
  3         4  
  3         71  
3 3     3   10 use Config;
  3         3  
  3         112  
4             our $VERSION = "0.18";
5 3     3   10 use File::Spec;
  3         9  
  3         2916  
6            
7             #============================================================================
8             # Object Interface
9             #============================================================================
10             sub new {
11 4     4 1 38 my $class = shift;
12 4         11 return bless { filter => shift, coderef => shift }, $class;
13             }
14              
15             sub filter {
16 4     4 1 13948 my ($self, $o, $code) = @_;
17 4         24 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         2 my $code = shift;
26 2         22 $code =~ s/^=\w+[^\n]*\n\n(.*?)(^=cut\n\n|\Z)//gsm;
27 2         5 return $code;
28             }
29              
30             #============================================================================
31             # Strip comments in various languages
32             #============================================================================
33             sub _skip_quoted {
34 4     4   3 my ($text, $index, $closer) = @_;
35 4         8 for (my $i=$index+1; $i
36 80         55 my $p = substr($text, $i-1, 1);
37 80         54 my $c = substr($text, $i, length($closer));
38 80 50 33     133 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         3 while (++$i < length $txt) {
47 359         199 my $closer;
48 359 100       239 if (grep {my $r=substr($txt,$i,length($_)) eq $_; $closer=$_ if $r; $r}
  359 100       258  
  359         383  
  359         476  
49             @quotes) {
50 4         6 $i = _skip_quoted($txt, $i, $closer);
51 4         7 next;
52             }
53 355 100       606 if (substr($txt, $i, length($opn)) eq $opn) {
54 3         4 my $e = index($txt, $cls, $i) + length($cls);
55 3         40 substr($txt, $i, $e-$i) =~ s/[^\n]/ /g;
56 3         4 $i--;
57 3         6 next;
58             }
59             }
60 2         4 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 2 my $ilsm = shift;
67 1         1 my $code = shift;
68 1         1 $code = _strip_comments($code, '//', "\n", '"');
69 1         2 $code = _strip_comments($code, '/*', '*/', '"');
70 1         3 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 1 my $ilsm = shift;
100 1         2 my $code = shift;
101              
102 1         1 my @inc_array;
103 1 50       3 if (defined($ilsm->{ILSM}{MAKEFILE}{INC})) {
104 1 50       3 if (ref($ilsm->{ILSM}{MAKEFILE}{INC} eq 'ARRAY')) {
105 0         0 @inc_array = @{$ilsm->{ILSM}{MAKEFILE}{INC}};
  0         0  
106             }
107             else {
108 1         3 @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         64 $cppflags,
122             "-I$Config{archlibexp}/CORE",
123             @inc_array
124             );
125              
126 1         24 my $tmpfile = File::Spec->catfile($ilsm->{API}{build_dir}, "Filters$$.c");
127 1         4 $ilsm->mkpath($ilsm->{API}{build_dir});
128 1         175 my ($CSRC, $PROCESSED);
129 1 50       106 open $CSRC, ">", $tmpfile or die $!;
130 1         6 print $CSRC $code;
131 1         44 close $CSRC;
132 1 50       1665 open $PROCESSED, "$cpp \"$tmpfile\" |" or die $!;
133 1         7116 $code = join '', <$PROCESSED>;
134 1         56 close $PROCESSED;
135 1         185 unlink $tmpfile;
136 1         47 return $code;
137             }
138              
139             #============================================================================
140             # Returns a list of key, value pairs; a filter and its code reference.
141             #============================================================================
142             my %filters =
143             (
144             ALL => [
145             Strip_POD => \&Strip_POD,
146             Preprocess => \&Preprocess,
147             ],
148             C => [
149             Strip_Comments => \&Strip_C_Comments,
150             ],
151             CPP => [
152             Strip_Comments => \&Strip_CPP_Comments,
153             ],
154             JAVA => [
155             Strip_Comments => \&Strip_CPP_Comments,
156             ],
157             );
158              
159             sub get_filters {
160 3     3 1 19 my $language = shift;
161 3         5 my ($all, $lang) = @filters{ALL => $language};
162 3   50     10 $lang ||= [];
163 3         12 return (@$all, @$lang);
164             }
165              
166             1;