home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 December (Special) / PCWorld_2005-12_Special_cd.bin / Bezpecnost / lsti / lsti.exe / framework-2.5.exe / Heavy.pm < prev    next >
Text File  |  2005-01-27  |  6KB  |  249 lines

  1. package Exporter::Heavy;
  2.  
  3. use strict;
  4. no strict 'refs';
  5.  
  6. # On one line so MakeMaker will see it.
  7. require Exporter;  our $VERSION = $Exporter::VERSION;
  8. $Carp::Internal{"Exporter::Heavy"} = 1;
  9.  
  10. =head1 NAME
  11.  
  12. Exporter::Heavy - Exporter guts
  13.  
  14. =head1 SYNOPSIS
  15.  
  16. (internal use only)
  17.  
  18. =head1 DESCRIPTION
  19.  
  20. No user-serviceable parts inside.
  21.  
  22. =cut
  23.  
  24. #
  25. # We go to a lot of trouble not to 'require Carp' at file scope,
  26. #  because Carp requires Exporter, and something has to give.
  27. #
  28.  
  29. sub _rebuild_cache {
  30.     my ($pkg, $exports, $cache) = @_;
  31.     s/^&// foreach @$exports;
  32.     @{$cache}{@$exports} = (1) x @$exports;
  33.     my $ok = \@{"${pkg}::EXPORT_OK"};
  34.     if (@$ok) {
  35.     s/^&// foreach @$ok;
  36.     @{$cache}{@$ok} = (1) x @$ok;
  37.     }
  38. }
  39.  
  40. sub heavy_export {
  41.  
  42.     # First make import warnings look like they're coming from the "use".
  43.     local $SIG{__WARN__} = sub {
  44.     my $text = shift;
  45.     if ($text =~ s/ at \S*Exporter\S*.pm line \d+.*\n//) {
  46.         require Carp;
  47.         local $Carp::CarpLevel = 1;    # ignore package calling us too.
  48.         Carp::carp($text);
  49.     }
  50.     else {
  51.         warn $text;
  52.     }
  53.     };
  54.     local $SIG{__DIE__} = sub {
  55.     require Carp;
  56.     local $Carp::CarpLevel = 1;    # ignore package calling us too.
  57.     Carp::croak("$_[0]Illegal null symbol in \@${1}::EXPORT")
  58.         if $_[0] =~ /^Unable to create sub named "(.*?)::"/;
  59.     };
  60.  
  61.     my($pkg, $callpkg, @imports) = @_;
  62.     my($type, $sym, $cache_is_current, $oops);
  63.     my($exports, $export_cache) = (\@{"${pkg}::EXPORT"},
  64.                                    $Exporter::Cache{$pkg} ||= {});
  65.  
  66.     if (@imports) {
  67.     if (!%$export_cache) {
  68.         _rebuild_cache ($pkg, $exports, $export_cache);
  69.         $cache_is_current = 1;
  70.     }
  71.  
  72.     if (grep m{^[/!:]}, @imports) {
  73.         my $tagsref = \%{"${pkg}::EXPORT_TAGS"};
  74.         my $tagdata;
  75.         my %imports;
  76.         my($remove, $spec, @names, @allexports);
  77.         # negated first item implies starting with default set:
  78.         unshift @imports, ':DEFAULT' if $imports[0] =~ m/^!/;
  79.         foreach $spec (@imports){
  80.         $remove = $spec =~ s/^!//;
  81.  
  82.         if ($spec =~ s/^://){
  83.             if ($spec eq 'DEFAULT'){
  84.             @names = @$exports;
  85.             }
  86.             elsif ($tagdata = $tagsref->{$spec}) {
  87.             @names = @$tagdata;
  88.             }
  89.             else {
  90.             warn qq["$spec" is not defined in %${pkg}::EXPORT_TAGS];
  91.             ++$oops;
  92.             next;
  93.             }
  94.         }
  95.         elsif ($spec =~ m:^/(.*)/$:){
  96.             my $patn = $1;
  97.             @allexports = keys %$export_cache unless @allexports; # only do keys once
  98.             @names = grep(/$patn/, @allexports); # not anchored by default
  99.         }
  100.         else {
  101.             @names = ($spec); # is a normal symbol name
  102.         }
  103.  
  104.         warn "Import ".($remove ? "del":"add").": @names "
  105.             if $Exporter::Verbose;
  106.  
  107.         if ($remove) {
  108.            foreach $sym (@names) { delete $imports{$sym} } 
  109.         }
  110.         else {
  111.             @imports{@names} = (1) x @names;
  112.         }
  113.         }
  114.         @imports = keys %imports;
  115.     }
  116.  
  117.         my @carp;
  118.     foreach $sym (@imports) {
  119.         if (!$export_cache->{$sym}) {
  120.         if ($sym =~ m/^\d/) {
  121.             $pkg->VERSION($sym); # inherit from UNIVERSAL
  122.             # If the version number was the only thing specified
  123.             # then we should act as if nothing was specified:
  124.             if (@imports == 1) {
  125.             @imports = @$exports;
  126.             last;
  127.             }
  128.             # We need a way to emulate 'use Foo ()' but still
  129.             # allow an easy version check: "use Foo 1.23, ''";
  130.             if (@imports == 2 and !$imports[1]) {
  131.             @imports = ();
  132.             last;
  133.             }
  134.         } elsif ($sym !~ s/^&// || !$export_cache->{$sym}) {
  135.             # Last chance - see if they've updated EXPORT_OK since we
  136.             # cached it.
  137.  
  138.             unless ($cache_is_current) {
  139.             %$export_cache = ();
  140.             _rebuild_cache ($pkg, $exports, $export_cache);
  141.             $cache_is_current = 1;
  142.             }
  143.  
  144.             if (!$export_cache->{$sym}) {
  145.             # accumulate the non-exports
  146.             push @carp,
  147.               qq["$sym" is not exported by the $pkg module\n];
  148.             $oops++;
  149.             }
  150.         }
  151.         }
  152.     }
  153.     if ($oops) {
  154.         require Carp;
  155.         Carp::croak("@{carp}Can't continue after import errors");
  156.     }
  157.     }
  158.     else {
  159.     @imports = @$exports;
  160.     }
  161.  
  162.     my($fail, $fail_cache) = (\@{"${pkg}::EXPORT_FAIL"},
  163.                               $Exporter::FailCache{$pkg} ||= {});
  164.  
  165.     if (@$fail) {
  166.     if (!%$fail_cache) {
  167.         # Build cache of symbols. Optimise the lookup by adding
  168.         # barewords twice... both with and without a leading &.
  169.         # (Technique could be applied to $export_cache at cost of memory)
  170.         my @expanded = map { /^\w/ ? ($_, '&'.$_) : $_ } @$fail;
  171.         warn "${pkg}::EXPORT_FAIL cached: @expanded" if $Exporter::Verbose;
  172.         @{$fail_cache}{@expanded} = (1) x @expanded;
  173.     }
  174.     my @failed;
  175.     foreach $sym (@imports) { push(@failed, $sym) if $fail_cache->{$sym} }
  176.     if (@failed) {
  177.         @failed = $pkg->export_fail(@failed);
  178.         foreach $sym (@failed) {
  179.                 require Carp;
  180.         Carp::carp(qq["$sym" is not implemented by the $pkg module ],
  181.             "on this architecture");
  182.         }
  183.         if (@failed) {
  184.         require Carp;
  185.         Carp::croak("Can't continue after import errors");
  186.         }
  187.     }
  188.     }
  189.  
  190.     warn "Importing into $callpkg from $pkg: ",
  191.         join(", ",sort @imports) if $Exporter::Verbose;
  192.  
  193.     foreach $sym (@imports) {
  194.     # shortcut for the common case of no type character
  195.     (*{"${callpkg}::$sym"} = \&{"${pkg}::$sym"}, next)
  196.         unless $sym =~ s/^(\W)//;
  197.     $type = $1;
  198.     *{"${callpkg}::$sym"} =
  199.         $type eq '&' ? \&{"${pkg}::$sym"} :
  200.         $type eq '$' ? \${"${pkg}::$sym"} :
  201.         $type eq '@' ? \@{"${pkg}::$sym"} :
  202.         $type eq '%' ? \%{"${pkg}::$sym"} :
  203.         $type eq '*' ?  *{"${pkg}::$sym"} :
  204.         do { require Carp; Carp::croak("Can't export symbol: $type$sym") };
  205.     }
  206. }
  207.  
  208. sub heavy_export_to_level
  209. {
  210.       my $pkg = shift;
  211.       my $level = shift;
  212.       (undef) = shift;            # XXX redundant arg
  213.       my $callpkg = caller($level);
  214.       $pkg->export($callpkg, @_);
  215. }
  216.  
  217. # Utility functions
  218.  
  219. sub _push_tags {
  220.     my($pkg, $var, $syms) = @_;
  221.     my @nontag = ();
  222.     my $export_tags = \%{"${pkg}::EXPORT_TAGS"};
  223.     push(@{"${pkg}::$var"},
  224.     map { $export_tags->{$_} ? @{$export_tags->{$_}} 
  225.                                  : scalar(push(@nontag,$_),$_) }
  226.         (@$syms) ? @$syms : keys %$export_tags);
  227.     if (@nontag and $^W) {
  228.     # This may change to a die one day
  229.     require Carp;
  230.     Carp::carp(join(", ", @nontag)." are not tags of $pkg");
  231.     }
  232. }
  233.  
  234. sub heavy_require_version {
  235.     my($self, $wanted) = @_;
  236.     my $pkg = ref $self || $self;
  237.     return ${pkg}->VERSION($wanted);
  238. }
  239.  
  240. sub heavy_export_tags {
  241.   _push_tags((caller)[0], "EXPORT",    \@_);
  242. }
  243.  
  244. sub heavy_export_ok_tags {
  245.   _push_tags((caller)[0], "EXPORT_OK", \@_);
  246. }
  247.  
  248. 1;
  249.