File Coverage

blib/lib/Parse/nm.pm
Criterion Covered Total %
statement 60 63 95.2
branch 16 22 72.7
condition 6 7 85.7
subroutine 9 9 100.0
pod 3 3 100.0
total 94 104 90.3


line stmt bran cond sub pod time code
1 4     4   134415 use strict;
  4         12  
  4         153  
2 4     4   24 use warnings;
  4         8  
  4         253  
3              
4             package Parse::nm;
5              
6             our $VERSION = '0.09';
7              
8 4     4   27 use Carp 'croak';
  4         18  
  4         230  
9 4     4   6044 use Regexp::Assemble;
  4         169571  
  4         153  
10 4     4   4827 use String::ShellQuote;
  4         6130  
  4         2715  
11              
12             sub new
13             {
14 2     2 1 31 my ($class, %args) = @_;
15 2         7 _build_filters(\%args);
16 2 50       13 return bless \%args, (ref $class ? ref $class : $class);
17             }
18              
19             sub _build_filters
20             {
21 16     16   34 my ($args) = @_;
22              
23 16 100 100     88 if (exists $args->{_comp_filters} && @{$args->{_comp_filters}}) {
  6         30  
24             # Copy data to preserve $self
25 4         9 $args->{_comp_filters} = [ @{$args->{_comp_filters}} ];
  4         12  
26 4         19 $args->{_re} = $args->{_re}->clone;
27             } else {
28 12         41 $args->{_comp_filters} = [];
29 12         107 $args->{_re} = Regexp::Assemble->new(fold_meta_pairs => 0);
30             }
31              
32 16 100       1884 if (exists $args->{filters}) {
33 14         27 my @f = @{$args->{filters}};
  14         47  
34 14         36 for my $f (@f) {
35 18   50     74 my $name = $f->{name} || '\S+';
36 18   100     86 my $type = $f->{type} || '[A-Z]';
37 18         185 $args->{_re}->add("^$name +$type +");
38 18         4777 push @{$args->{_comp_filters}}, [
  18         557  
39             qr/^($name) +($type) +/, $f->{action}
40             ];
41             }
42 14         47 delete $args->{filters};
43             }
44             }
45              
46              
47             sub run
48             {
49 1     1 1 139718 my ($self, %args) = @_;
50 1 50       18 %args = (%{$self}, %args) if ref $self;
  0         0  
51              
52 1 50       13 my @options = exists $args{options} ? @{$args{options}} : ();
  0         0  
53 1 50       10 my @files = ref $args{files} ? @{$args{files}} : ($args{files});
  0         0  
54              
55 1         5 my $nm;
56             {
57             # have to turn this on to get POSIX-ish output from nm -P on Irix
58 1 50       9 local $ENV{_XPG} = '1' if ($^O eq 'irix');
  1         17  
59              
60             #open $nm, 'nm '.join(' ', map { my $x = $_; $x =~ s/"/\\"/g; qq{"$x"} } @files).' |'
61 1 50       28 open $nm, '-|', shell_quote('nm', '-P', @options, @files)
62             or croak "Can't run 'nm': $!";
63             }
64 1         10884 my $r = $self->parse($nm, %args);
65 1         47 close $nm;
66 1         19 return $r;
67             }
68              
69              
70             sub parse
71             {
72 14     14 1 8847 my ($self, $handle, %args) = @_;
73 14 100       72 %args = (%{$self}, %args) if ref $self;
  6         37  
74 14         61 _build_filters(\%args);
75 14         63 my $re = $args{_re}->re;
76 14         9276 my $filters = $args{_comp_filters};
77 14         94 while (<$handle>) {
78 24 100       169 next unless /$re/;
79 20         31 for my $f (@{$filters}) {
  20         49  
80 40 100       22174 if (/$f->[0]/) {
81 20         150 $f->[1]($1, $2);
82             }
83             }
84             }
85 14         57377 return ();
86             }
87              
88             1;
89             __END__