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