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