File Coverage

blib/lib/TAPx/Parser/Source/Perl.pm
Criterion Covered Total %
statement 79 82 96.3
branch 22 32 68.7
condition 7 13 53.8
subroutine 14 14 100.0
pod 2 2 100.0
total 124 143 86.7


line stmt bran cond sub pod time code
1             package TAPx::Parser::Source::Perl;
2              
3 12     12   436 use strict;
  12         22  
  12         543  
4 12     12   68 use vars qw($VERSION @ISA);
  12         21  
  12         1141  
5              
6 12     12   77 use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ );
  12         37  
  12         928  
7 12     12   110 use constant IS_MACOS => ( $^O eq 'MacOS' );
  12         24  
  12         641  
8 12     12   58 use constant IS_VMS => ( $^O eq 'VMS' );
  12         25  
  12         499  
9              
10 12     12   68 use TAPx::Parser::Iterator;
  12         31  
  12         346  
11 12     12   60 use TAPx::Parser::Source;
  12         24  
  12         20908  
12             @ISA = 'TAPx::Parser::Source';
13              
14             =head1 NAME
15              
16             TAPx::Parser::Source::Perl - Stream Perl output
17              
18             =head1 VERSION
19              
20             Version 0.50_07
21              
22             =cut
23              
24             $VERSION = '0.50_07';
25              
26             =head1 DESCRIPTION
27              
28             Takes a filename and hopefully returns a stream from it. The filename should
29             be the name of a Perl program.
30              
31             Note that this is a subclass of L. See that module for
32             more methods.
33              
34             =head1 SYNOPSIS
35              
36             use TAPx::Parser::Source::Perl;
37             my $perl = TAPx::Parser::Source::Perl->new;
38             my $stream = $perl->source($filename)->get_stream;
39              
40             =head1 METHODS
41              
42             =head2 Class methods
43              
44             =head3 C
45              
46             my $perl = TAPx::Parser::Source::Perl->new;
47              
48             Returns a new C object.
49              
50             =head2 Instance methods
51              
52             =head3 C
53              
54             my $perl = $source->source;
55             $perl->source($filename);
56              
57             Getter/setter for the source filename. Will C if the C<$filename> does
58             not appear to be a file.
59              
60             =cut
61              
62             sub source {
63 121     121 1 214 my $self = shift;
64 121 100       408 return $self->{source} unless @_;
65 40         71 my $filename = shift;
66 40 50       928 unless ( -f $filename ) {
67 0         0 $self->_croak("Cannot find ($filename)");
68             }
69 40         117 $self->{source} = $filename;
70 40         855 return $self;
71             }
72              
73             =head3 C
74              
75             my $switches = $perl->switches;
76             my @switches = $perl->switches;
77             $perl->switches(\@switches);
78              
79             Getter/setter for the additional switches to pass to the perl executable. One
80             common switch would be to set an include directory:
81              
82             $perl->switches('-Ilib');
83              
84             =cut
85              
86             sub switches {
87 80     80 1 297 my $self = shift;
88 80 100       256 unless (@_) {
89 41 50       132 return wantarray ? @{ $self->{switches} } : $self->{switches};
  41         325  
90             }
91 39         66 my $switches = shift;
92 39         174 $self->{switches} = [@$switches]; # force a copy
93 39         145 return $self;
94             }
95              
96             sub _get_command {
97 40     40   66 my $self = shift;
98 40         3615 my $file = $self->source;
99 40         295 my $command = $self->_get_perl;
100 40         197 my @switches = $self->_switches;
101              
102 40 50 33     324 $file = qq["$file"] if ( $file =~ /\s/ ) && ( $file !~ /^".*"$/ );
103 40         155 my @command = ( $command, @switches, $file );
104              
105             #use Data::Dumper;
106             #warn Dumper(\@command);
107 40         332 return @command;
108             }
109              
110             sub _switches {
111 41     41   128 my $self = shift;
112 41         118 my $file = $self->source;
113 41         120 my @switches = (
114             $self->switches,
115             );
116              
117 41         192 local *TEST;
118 41 50       2230 open( TEST, $file ) or print "can't open $file. $!\n";
119 41         1126 my $shebang = ;
120 41 50       1104 close(TEST) or print "can't close $file. $!\n";
121              
122 41         256 my $taint = ( $shebang =~ /^#!.*\bperl.*\s-\w*([Tt]+)/ );
123 41 100       196 push( @switches, "-$1" ) if $taint;
124              
125             # When taint mode is on, PERL5LIB is ignored. So we need to put
126             # all that on the command line as -Is.
127             # MacPerl's putenv is broken, so it will not see PERL5LIB, tainted or not.
128 41 100 100     344 if ( $taint || IS_MACOS ) {
129 4         28 my @inc = $self->_filtered_inc;
130 4         14 push @switches, map {"-I$_"} @inc;
  20         84  
131             }
132              
133             # Quote the argument if there's any whitespace in it, or if
134             # we're VMS, since VMS requires all parms quoted. Also, don't quote
135             # it if it's already quoted.
136 41         152 for (@switches) {
137 86 50 50     802 $_ = qq["$_"] if ( ( /\s/ || IS_VMS ) && !/^".*"$/ );
      33        
138             }
139              
140 41         102 my %found_switch = map { $_ => 0 } @switches;
  86         672  
141              
142             # remove duplicate switches
143             @switches
144 41 100 66     152 = grep { defined $_ && $_ ne '' && !$found_switch{$_}++ } @switches;
  86         849  
145 41         385 return @switches;
146             }
147              
148             sub _filtered_inc {
149 4     4   20 my $self = shift;
150 4         13 my @inc = @_;
151 4 50       131 @inc = @INC unless @inc;
152              
153 4 50       29 if (IS_VMS) {
154              
155             # VMS has a 255-byte limit on the length of %ENV entries, so
156             # toss the ones that involve perl_root, the install location
157             @inc = grep !/perl_root/i, @inc;
158              
159             }
160 0         0 elsif (IS_WIN32) {
161              
162             # Lose any trailing backslashes in the Win32 paths
163 0         0 s/[\\\/+]$// foreach @inc;
164             }
165              
166 4         15 my %seen;
167 4         24 $seen{$_}++ foreach $self->_default_inc;
168 4         253 @inc = grep !$seen{$_}++, @inc;
169              
170 4         47 return @inc;
171             }
172              
173             {
174              
175             # cache this to avoid repeatedly shelling out to Perl. This really speeds
176             # up TAPx::Parser.
177             my @inc;
178              
179             sub _default_inc {
180 4 100   4   58 return @inc if @inc;
181 2         4 my $proto = shift;
182 2         23 local $ENV{PERL5LIB};
183 2         8 my $perl = $proto->_get_perl;
184 2         32426 chomp( @inc = `$perl -le "print join qq[\\n], \@INC"` );
185 2         249 return @inc;
186             }
187             }
188              
189             sub _get_perl {
190 42     42   72 my $proto = shift;
191 42 50       186 return $ENV{HARNESS_PERL} if defined $ENV{HARNESS_PERL};
192 42 50       270 return Win32::GetShortPathName($^X) if IS_WIN32;
193 42         116 return $^X;
194             }
195              
196             1;