File Coverage

blib/lib/IfLoop.pm
Criterion Covered Total %
statement 90 96 93.7
branch 20 34 58.8
condition 4 8 50.0
subroutine 12 14 85.7
pod 0 5 0.0
total 126 157 80.2


line stmt bran cond sub pod time code
1             package IfLoop;
2              
3 1     1   16374 use 5.006;
  1         4  
  1         40  
4 1     1   6 use strict;
  1         1  
  1         35  
5 1     1   4 use warnings;
  1         14  
  1         68  
6              
7 1     1   30390 use Filter::Util::Call;
  1         2478  
  1         74  
8 1     1   1438 use Text::Balanced;
  1         49719  
  1         1526  
9              
10             #require Exporter;
11             #our @ISA = qw(Exporter);
12             # Items to export into callers namespace by default. Note: do not export
13             # names by default without a very good reason. Use EXPORT_OK instead.
14             # Do not simply export all your public functions/methods/constants.
15              
16             # This allows declaration use IfLoop ':all';
17             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
18             # will save memory.
19             #our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
20             #our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
21             #our @EXPORT = qw();
22              
23             our $VERSION = '0.03';
24             our $DEBUG = 0;
25              
26             # Helps tell us about where in the file we are.
27             my $offset;
28              
29             #---------------------------------------------------------------------------
30             #---------------------------------------------------------------------------
31             sub line
32             {
33 0     0 0 0 my ($pretext,$offset) = @_;
34 0   0     0 ($pretext=~tr/\n/\n/)+($offset||0);
35             }
36              
37             #---------------------------------------------------------------------------
38             #---------------------------------------------------------------------------
39             sub import
40             {
41 1     1   10 my($type, @arguments) = @_ ;
42              
43 1 50       6 if(scalar(@arguments) == 0)
44             {
45 1         4 @arguments = qw(while until);
46             }
47            
48 1         4 my $tmp = join ':1:', @arguments,':1';
49 1         7 @arguments = split ':', $tmp;
50              
51 1         5 $offset = (caller)[2]+1;
52 1         10 filter_add({@arguments}) ;
53             }
54              
55             #---------------------------------------------------------------------------
56             #---------------------------------------------------------------------------
57             sub unimport
58             {
59 0     0   0 filter_del();
60             }
61              
62             #---------------------------------------------------------------------------
63             #---------------------------------------------------------------------------
64             sub handle_filehandles
65             {
66 11     11 0 18 my $bool_condition = shift;
67 11         14 my $r_source = shift;
68 11         14 my $line = shift;
69              
70 11         103 my @pos = Text::Balanced::_match_codeblock(\$bool_condition,
71             qr/\s*/,
72             qr/\(/,qr/\)/,
73             qr/[(<]/,qr/[>)]/,
74             undef);
75 11 50       23598 if(@pos)
76             {
77 11         30 my $tmp = substr($bool_condition,$pos[0],$pos[4]-$pos[0]);
78 11 50       60 if($tmp =~ m/(<.*>)/)
79             {
80 0         0 my $file_access = $`.$1;
81 0 0       0 if($file_access !~ m/\$\_\s*=\s*<.*>/o)
82             {
83 0         0 die "Filehandles \"\" must be used like \"\$_ = \"\n".
84             "Like the normal \"if-elsif-else\" syntax. \$_ is not set automagically!\n".
85             "Check bool statement: $bool_condition part of chain near line# ".
86             &line(substr($$r_source,0,pos $$r_source),$line)."\n";
87             }
88             }
89             }
90             }
91              
92             #---------------------------------------------------------------------------
93             #---------------------------------------------------------------------------
94             sub filter
95             {
96 2     2 0 36 my $self = shift ;
97 2         6 my $status;
98            
99 2         69 $status = filter_read(100_000);
100 2 50       11 return $status if($status < 0);
101              
102 2         9 $_ = &filter_blocks($self,$_,$offset);
103              
104 2         3865 $status ;
105             }
106              
107             #---------------------------------------------------------------------------
108             #---------------------------------------------------------------------------
109             sub filter_blocks
110             {
111             #Many a regex shamelessly stolen from Damian's Switch module.
112              
113 10     10 0 31 my $self = shift;
114 10         22 my $source = shift;
115 10         14 my $line = shift;
116              
117 10         15 my $keyword = '';
118              
119 10   100     525 while($source =~ m/(\n*)(\s*)((elsif|if)until)\b(?=\s*[(])(?{$keyword = $3})/gc ||
120             $source =~ m/(\n*)(\s*)((elsif|if)while)\b(?=\s*[(])(?{$keyword = $3})/gc )
121            
122             {
123 11         18 my $r_fctn;
124 11         70 my %args = (self => $self,
125             r_source => \$source,
126             line => $line,
127             keyword => $keyword);
128              
129 11         68 $keyword =~ m/(?:if|elsif)(.*)/;
130             {
131 1     1   15 no strict 'refs';
  1         1  
  1         140  
  11         18  
132 11         23 my $base_keyword = $1;
133              
134 11 50 33     73 next if(!$self->{$base_keyword} || !$base_keyword);
135 11         17 $r_fctn = \&{${base_keyword}.'_key'};
  11         48  
136             }
137              
138 11 50       103 $r_fctn->(\%args) if(ref($r_fctn) eq 'CODE');
139             }
140 10 50       56 print STDERR $source if($DEBUG);
141 10         52 return $source;
142             }
143              
144             #---------------------------------------------------------------------------
145             #---------------------------------------------------------------------------
146 1     1   6 { no warnings; *while_key = *until_key = \&while_until_key; }
  1         3  
  1         892  
147              
148             sub while_until_key
149             {
150 11     11 0 18 my $r_args = shift;
151 11         18 my $self = $r_args->{self};
152 11         19 my $r_source = $r_args->{r_source};
153 11         19 my $line = $r_args->{line};
154 11         19 my $keyword = $r_args->{keyword};
155            
156 11         32 pos $$r_source = pos($$r_source);
157            
158 11         362 my @pos = Text::Balanced::_match_codeblock($r_source,
159             qr/\s*/,
160             qr/\(/,qr/\)/,
161             qr/[{(]/,qr/[)}]/,
162             undef);
163            
164             #Capture \G so that if we encounter comments
165             # in the chain we can reset and go back for another pass.
166 11         9010 my $pos_G = pos $$r_source;
167              
168 11 50       36 print STDERR "|@pos|\n" if($DEBUG);
169 11 50       64 print STDERR substr($$r_source,$pos[0]-10,$pos[4]-$pos[0]+10),"\n" if($DEBUG);
170            
171             #substr($source,$pos[0]-10,$pos[4]-$pos[0]+10) #grabs elsewhile(...);
172             #substr($source,$pos[0],$pos[4]-$pos[0]) #grabs (...);
173            
174 11         29 my $bool_condition = substr($$r_source,$pos[0],$pos[4]-$pos[0]);
175 11         27 my @replace=($pos[0]-7); #default replace starting place for an "if"
176 11         16 my $text = 'if'; #default replacement for an "if"
177            
178             #change the @replace array and the $text if the statement is not an "if"
179 11 100       41 if($keyword =~ m/elsif.*/)
180             {
181 2         5 $text = "elsif";
182 2         3 $replace[0] = $pos[0]-10; #It just so happens that until and while
183             #both have five letters in them.
184             }
185            
186             #Filehandles that set $_ are speeeeecial Mmm-Kay
187             # lets die and warn the user with some position information.
188 11         31 &handle_filehandles($bool_condition,$r_source,$line);
189            
190             #Adjust the syntax of the if to account for until. HA!
191 11 100       41 if($keyword =~ m/.*until/){$text .= "(!$bool_condition)\{do";}
  3         9  
  8         640  
192             else {$text .= "$bool_condition\{do"; }
193            
194 11         114 @pos = Text::Balanced::_match_codeblock($r_source,
195             qr/\s*/,
196             qr/\{/,qr/\}/,
197             qr/\{/,qr/\}/,
198             undef);
199 11 50       19430 print STDERR "|@pos|\n" if($DEBUG);
200 11 50       33 print STDERR substr($$r_source,$pos[0],$pos[4]-$pos[0]),"\n" if($DEBUG);
201            
202             #If no positions are present then we must be doing the comment thing...
203 11 100       36 if(scalar @pos)
204             {
205 8         29 my $inner = substr($$r_source,$pos[0],$pos[4]-$pos[0]);
206            
207 8         26 push @replace, ($pos[4]-$pos[0])+$pos[0];
208            
209             #Allow N number of nests for the syntax.
210 8         34 $inner = &filter_blocks($self,$inner,$line);
211            
212             #Adjust the syntax of the if to account for until. HA!
213 8 100       33 if($keyword =~ m/.*until/)
214             {
215 3         13 $text .= $inner."until$bool_condition}";
216             }
217             else
218             {
219 5         20 $text .= $inner."while$bool_condition}";
220             }
221            
222 8 50       21 print STDERR "|@replace|" if($DEBUG);
223            
224 8         6122 substr($$r_source,$replace[0],$replace[1]-$replace[0],$text);
225             }
226             else
227             {
228 3         124 pos $$r_source = $pos_G;
229             }
230              
231             }# End fctn while_until_key;
232              
233              
234             1;
235             __END__