Stash.pm 7.0 KB

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