File Coverage

blib/lib/B/Stash.pm
Criterion Covered Total %
statement 0 109 0.0
branch 0 82 0.0
condition 0 18 0.0
subroutine 0 10 0.0
pod 0 7 0.0
total 0 226 0.0


line stmt bran cond sub pod time code
1             # Stash.pm -- show what stashes are loaded
2             package B::Stash;
3              
4             our $VERSION = '1.03';
5              
6             =pod
7              
8             =head1 NAME
9              
10             B::Stash - show what stashes are loaded
11              
12             =head1 DESCRIPTION
13              
14             B::Stash has a poor side-effect only API and is only used by perlcc and L,
15             and there its usability is also inferior.
16              
17             It hooks into B and prints a comma-seperated list of loaded stashes
18             (I) prefixed with B<-u>.
19              
20             With the B option stashes with XS modules only are printed, prefixed with B<-x>.
21              
22             With the B<-D> option some debugging output is added.
23              
24             Note that the resulting list of modules from B::Stash is usually larger and more
25             inexact than the list of used modules determined by the compiler suite (C, CC, Bytecode).
26              
27             =head1 SYNOPSIS
28              
29             # typical usage:
30             perlcc -stash -e'use IO::Handle;'
31              
32             perlcc -stash -v3 -e'use IO::Handle;'
33             =>
34             ...
35             Stash: main strict Cwd Regexp Exporter Exporter::Heavy warnings DB
36             attributes Carp Carp::Heavy Symbol PerlIO SelectSaver
37             ...
38              
39             perl -c -MB::Stash -e'use IO::Handle;'
40             => -umain,-uIO
41              
42             perl -c -MB::Stash=xs -e'use IO::Handle;'
43             => -xre,-xCwd,-xRegexp,-xIO
44              
45             perl -c -MO=Stash=xs,-D -e'use IO::Handle;'
46             ...
47             => -xre,-xCwd,-xRegexp,-xIO
48              
49             perl -c -MO=C,-dumpxs -e'use IO::Handle;'
50             ...
51             perlcc.lst: -xre,-xCwd,-xRegexp,-xIO
52              
53             =cut
54              
55             # BEGIN { %Seen = %INC }
56              
57             sub import {
58 0     0     my ($class, @options) = @_;
59 0           my $opts = ",".join(",", @options).",";
60 0           my $xs = $opts =~ /,xs,/;
61 0           my $debug = $opts =~ /,-D,/;
62 0 0         print "import: ",$class,$opts,"\n" if $debug;
63 0 0         unless ($xs) {
64 0 0         eval q[
65             CHECK {
66             ] . ($debug ? q[print "scan main\n"; my $debug=1;] : "") . q[
67             my @arr = scan( $main::{"main::"},'',$debug );
68             @arr = map { s/\:\:$//; $_ eq "" ? () : $_; } @arr;
69             print "-umain,-u", join( ",-u", @arr ), "\n";
70             } ];
71             } else {
72 0 0         eval q[
73             CHECK {
74             ] . ($debug ? q[print "scanxs main\n"; my $debug=1;] : "") . q[
75             #line 2 B/Stash.pm
76             require XSLoader;
77             XSLoader::load('B::Stash'); # for xs only
78             my @arr = scanxs( $main::{"main::"},'',$debug );
79             @arr = map { s/\:\:$//; $_ eq "" ? () : $_; } @arr;
80             print "-x", join( ",-x", @arr ), "\n";
81             } ];
82             }
83             }
84              
85             # new O interface, esp. for debugging
86             sub compile {
87 0     0 0   my @options = @_;
88 0           my $opts = ",".join(",", @options).",";
89 0           my $xs = $opts =~ /,xs,/;
90 0           my $debug = $opts =~ /,-D,/;
91 0 0         print "import: ",$class,$opts,"\n" if $debug;
92 0 0         unless ($xs) {
93 0 0         print "scan main\n" if $debug;
94             return sub {
95 0     0     my @arr = scan( $main::{"main::"},'',$debug );
96 0 0         @arr = map { s/\:\:$//; $_ eq "" ? () : $_; } @arr;
  0            
  0            
97 0           print "-umain,-u", join( ",-u", @arr ), "\n";
98             }
99 0           } else {
100 0           require XSLoader;
101 0           XSLoader::load('B::Stash'); # for xs only
102 0 0         print "scanxs main\n" if $debug;
103             return sub {
104 0     0     my @arr = scanxs( $main::{"main::"},'',$debug );
105 0 0         @arr = map { s/\:\:$//; $_ eq "" ? () : $_; } @arr;
  0            
  0            
106 0           print "-x", join( ",-x", @arr ), "\n";
107             }
108 0           }
109             }
110              
111             sub scan {
112 0     0 0   my $start = shift;
113 0           my $prefix = shift;
114 0           my $debug = shift;
115 0 0         $prefix = '' unless defined $prefix;
116 0           my @return;
117 0           foreach my $key ( grep /::$/, keys %{$start} ) {
  0            
118 0           my $name = $prefix . $key;
119 0 0         print $name,"\n" if $debug;
120 0 0 0       unless ( $start eq ${$start}{$key} or omit($name) ) {
  0            
121 0 0         push @return, $key unless $name eq "version::"; # version has an external ::vxs module
122 0           foreach my $subscan ( scan( ${$start}{$key}, $name ) ) {
  0            
123 0           my $subname = $key.$subscan;
124 0 0         print $subname,"\n" if $debug;
125 0           push @return, $subname;
126             }
127             }
128             }
129 0           return @return;
130             }
131              
132             sub omit {
133 0     0 0   my $name = shift;
134 0           my %omit = (
135             "DynaLoader::" => 1,
136             "XSLoader::" => 1,
137             "CORE::" => 1,
138             "CORE::GLOBAL::" => 1,
139             "UNIVERSAL::" => 1,
140             "B::" => 1, # inexact. There could be interesting external B modules
141             "O::" => 1,
142             'PerlIO::Layer::'=> 1, # inexact. Only find|NoWarnings should be skipped
143             );
144 0           my %static_core_pkg = map {$_ => 1} static_core_packages();
  0            
145 0 0         return 1 if $omit{$name};
146 0 0         return 1 if $static_core_pkg{substr($name,0,-2)};
147 0 0 0       if ( $name eq "IO::" or $name eq "IO::Handle::" ) {
148 0           $name =~ s/::/\//g;
149 0 0         return 1 unless $INC{$name};
150             }
151              
152 0           return 0;
153             }
154              
155             # external XS modules only
156             sub scanxs {
157 0     0 0   my $start = shift;
158 0           my $prefix = shift;
159 0           my $debug = shift;
160 0 0         $prefix = '' unless defined $prefix;
161 0           my %IO = (IO::File:: => 1,
162             IO::Handle:: => 1,
163             IO::Socket:: => 1,
164             IO::Seekable:: => 1,
165             IO::Poll:: => 1);
166 0           my @return;
167 0           foreach my $key ( grep /::$/, keys %{$start} ) {
  0            
168 0           my $name = $prefix . $key;
169 0 0         print $name,"\n" if $debug;
170 0 0         $name = "IO" if $IO{$name};
171 0 0 0       unless ( $start eq ${$start}{$key} or omit($name) ) {
  0            
172 0 0 0       push @return, $name if has_xs($name, $debug) and $name ne "version::";
173 0           foreach my $subscan ( scanxs( ${$start}{$key}, $name, $debug ) ) {
  0            
174 0           my $subname = $key.$subscan;
175 0 0         print $subname,"\n" if $debug;
176             # there are more interesting version subpackages
177 0 0 0       push @return, $subname if !omit($subname) and has_xs($subname, $debug)
      0        
178             and $name ne "version::";
179             }
180             }
181             }
182 0           return @return;
183             }
184              
185             sub has_xs {
186 0     0 0   my $name = shift;
187 0           my $debug = shift;
188 0           foreach my $key ( keys %{$name} ) {
  0            
189 0           my $cvname = $name . $key;
190 0 0         if (CvIsXSUB($cvname)) {
191 0 0         print "has_xs: &",$cvname," -> 1\n" if $debug;
192 0 0         return 0 if in_static_core(substr($name,0,-2), $key);
193 0           return 1;
194             }
195             }
196 0           return 0;
197             }
198              
199             # Keep in sync with B::C
200             # XS in CORE which do not need to be bootstrapped extra.
201             # There are some specials like mro,re,UNIVERSAL.
202             sub in_static_core {
203 0     0 0   my ($stashname, $cvname) = @_;
204 0 0         if ($stashname eq 'UNIVERSAL') {
205 0           return $cvname =~ /^(isa|can|DOES|VERSION)$/;
206             }
207 0 0         return 1 if $static_core_pkg{$stashname};
208 0 0         if ($stashname eq 'mro') {
209 0           return $cvname eq 'method_changed_in';
210             }
211 0 0         if ($stashname eq 're') {
212 0           return $cvname =~ /^(is_regexp|regname|regnames_count|regexp_pattern)$/;;
213             }
214 0 0         if ($stashname eq 'PerlIO') {
215 0           return $cvname eq 'get_layers';
216             }
217 0 0         if ($stashname eq 'PerlIO::Layer') {
218 0           return $cvname =~ /^(find|NoWarnings)$/;
219             }
220 0           return 0;
221             }
222              
223             # Keep in sync with B::C
224             # XS modules in CORE. Reserved namespaces.
225             # Note: mro,re,UNIVERSAL have both, static core and dynamic/static XS.
226             # version has an external ::vxs
227             sub static_core_packages {
228 0     0 0   my @pkg = qw(Internals utf8 UNIVERSAL);
229 0 0         push @pkg, qw(Tie::Hash::NamedCapture) if $] >= 5.010;
230 0 0         push @pkg, qw(DynaLoader) if $Config{usedl};
231             # Win32CORE only in official cygwin pkg. And it needs to be bootstrapped,
232             # handled by static_ext.
233 0 0         push @pkg, qw(Cygwin) if $^O eq 'cygwin';
234 0 0         push @pkg, qw(NetWare) if $^O eq 'NetWare';
235 0 0         push @pkg, qw(OS2) if $^O eq 'os2';
236 0 0         push @pkg, qw(VMS VMS::Filespec vmsish) if $^O eq 'VMS';
237             #push @pkg, qw(PerlIO) if $] >= 5.008006; # get_layers only
238 0           return @pkg;
239             }
240              
241             1;
242              
243             __END__