| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | =head1 NAME | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | AutoReloader - Lazy loading and reloading of anonymous subroutines | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | use AutoReloader; | 
| 8 |  |  |  |  |  |  | my $sub = AutoReloader -> new ($file, $checksub, $autoprefix); | 
| 9 |  |  |  |  |  |  | $result = $sub -> (@args); | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | $sub -> check (0);           # turn source file checking off for $sub | 
| 12 |  |  |  |  |  |  | $sub -> checksub ($coderef); # provide alternative checking routine | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | use AutoReloader qw (AUTOLOAD); | 
| 15 |  |  |  |  |  |  | AutoReloader -> check (1);      # turn source file checking on | 
| 16 |  |  |  |  |  |  | $result = somefunc (@args); | 
| 17 |  |  |  |  |  |  | *somefunc{CODE}->check(0);   # turn off checking for this named sub | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | AutoReloader provides lazy loading like AutoLoader, but for function files | 
| 22 |  |  |  |  |  |  | which return an anonymous subroutine upon require. | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | Before requiring that file, it is checked via some subroutine returning | 
| 25 |  |  |  |  |  |  | a value (default is mtime). The returned value is remembered. At each | 
| 26 |  |  |  |  |  |  | call to that sub the check subroutine is run again, and if the returned | 
| 27 |  |  |  |  |  |  | value changed, the source file is reloaded. | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | Importing the AUTOLOAD method provides for lazy loading of anonsubs as | 
| 30 |  |  |  |  |  |  | named subs. The wrapped anonsub will be assigned to a symbol table entry | 
| 31 |  |  |  |  |  |  | named after the filename root of the function source file. | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | =head1 METHODS | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | =over 4 | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | =item new ($file, $checksubref, $autoprefix) | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | subroutine constructor. $file can be the path to some function file or | 
| 40 |  |  |  |  |  |  | a function name which will be expanded to $autoprefix/__PACKAGE__/$function.al | 
| 41 |  |  |  |  |  |  | and searched for in @INC. $checksubref and $autoprefix are optional. | 
| 42 |  |  |  |  |  |  | If they are not provided, the default class settings are used. | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | =item auto ($autoprefix) | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | set or get the default autoprefix. Default is 'auto', just as with AutoLoader: | 
| 47 |  |  |  |  |  |  | for e.g. POSIX::rand the source file would be auto/POSIX/rand.al . AutoReloader | 
| 48 |  |  |  |  |  |  | lets you replace the 'auto' part of the path with something else. Class method | 
| 49 |  |  |  |  |  |  | (for now). | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | =item suffix ($suffix) | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | set or get the suffix of your autoloaded files (e.g. '.al', '.pl', '.tmpl') | 
| 54 |  |  |  |  |  |  | as a package variable. | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | =item check (1) | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | set or get the check flag. Turn checking on by setting this to some true value. | 
| 59 |  |  |  |  |  |  | Default is off. Class and object method, i.e. AutoReloader->check(1) sets the | 
| 60 |  |  |  |  |  |  | default to on, $sub->check(1) sets checking for a subroutine. For now, there's | 
| 61 |  |  |  |  |  |  | no way to inculcate the class default on subs with a private check flag. | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =item checksub ($coderef) | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | set the checking subroutine. Class and object method. This subroutine will be | 
| 66 |  |  |  |  |  |  | invoked with a subroutines source filename (full path) every time the sub for | 
| 67 |  |  |  |  |  |  | which it is configured - but only if check for that subroutine is true -, and | 
| 68 |  |  |  |  |  |  | should return some value special to that file. | 
| 69 |  |  |  |  |  |  | Default is 'sub { (stat $_[0]) [9] }', i.e. mtime. | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | =back | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | AutoLoader, AutoSplit, DBIx::VersionedSubs | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | =head1 BUGS | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | AutoReloader subroutines are always reported as __ANON__ (e.g. with Carp::cluck), | 
| 80 |  |  |  |  |  |  | even if they are assigned to a symbol table entry. Which might not be a bug. | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | There might be others. | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | =head1 Author | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | shmem | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | =head1 CREDITS | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | Many thanks to thospel, Corion, diotalevi, tye and chromatic (these are their | 
| 91 |  |  |  |  |  |  | http://perlmonks.org nicks) for review and most valuable hints. | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | =head1 COPYRIGHT | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | Copyright 2007 - 2021 by shmem | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it | 
| 98 |  |  |  |  |  |  | under the same terms as Perl itself. | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | =cut | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | package AutoReloader; | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 4 |  |  | 4 |  | 284885 | use strict; | 
|  | 4 |  |  |  |  | 34 |  | 
|  | 4 |  |  |  |  | 123 |  | 
| 105 | 4 |  |  | 4 |  | 21 | use warnings; | 
|  | 4 |  |  |  |  | 7 |  | 
|  | 4 |  |  |  |  | 122 |  | 
| 106 | 4 |  |  | 4 |  | 31 | use Scalar::Util; | 
|  | 4 |  |  |  |  | 8 |  | 
|  | 4 |  |  |  |  | 168 |  | 
| 107 | 4 |  |  | 4 |  | 24 | use File::Spec; | 
|  | 4 |  |  |  |  | 9 |  | 
|  | 4 |  |  |  |  | 203 |  | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | our $VERSION   = 0.03; | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 4 |  |  | 4 |  | 29 | use vars qw($Debug %AL); | 
|  | 4 |  |  |  |  | 7 |  | 
|  | 4 |  |  |  |  | 4423 |  | 
| 112 |  |  |  |  |  |  | $Debug = 0; | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | sub new { | 
| 115 | 2 |  |  | 2 | 1 | 318 | my $class  = shift; | 
| 116 | 2 |  |  |  |  | 6 | my $caller = caller; | 
| 117 | 2 |  |  |  |  | 8 | my $sub    = gensub ($caller,@_); | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 2 |  |  |  |  | 7 | bless $sub, $class; | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | sub auto { | 
| 123 | 5 |  |  | 5 | 1 | 831 | shift if __PACKAGE__ || $_[0] eq (caller(0))[0]; | 
| 124 | 5 | 100 |  |  |  | 27 | $AL {'auto'} = shift if @_; | 
| 125 | 5 |  |  |  |  | 21 | $AL {'auto'}; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | sub check { | 
| 129 | 8 |  |  | 8 | 1 | 2002979 | my $self = shift; | 
| 130 | 8 | 100 |  |  |  | 32 | if(ref($self)) { | 
| 131 | 3 | 50 |  |  |  | 21 | ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'check'} } | 
|  | 3 |  |  |  |  | 29 |  | 
| 132 |  |  |  |  |  |  | = shift if @_; | 
| 133 | 3 |  |  |  |  | 9 | ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'check'} }; | 
|  | 3 |  |  |  |  | 16 |  | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  | else { | 
| 136 | 5 |  |  |  |  | 11 | $AL {'check'}  = shift; | 
| 137 | 5 |  |  |  |  | 9 | $AL {'check'}; | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | sub checksub { | 
| 142 | 6 |  |  | 6 | 1 | 1110 | my $self = shift; | 
| 143 | 6 | 100 |  |  |  | 21 | if(ref($self)) { | 
| 144 | 2 | 100 |  |  |  | 12 | ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'checksub'} } | 
|  | 1 |  |  |  |  | 7 |  | 
| 145 |  |  |  |  |  |  | = shift if @_; | 
| 146 | 2 |  |  |  |  | 5 | ${ $AL {'Sub'} -> {Scalar::Util::refaddr ($self)} -> {'checksub'} }; | 
|  | 2 |  |  |  |  | 16 |  | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  | else { | 
| 149 | 4 | 50 |  |  |  | 18 | $AL {'checksub'} = shift if @_; | 
| 150 | 4 |  |  |  |  | 8 | $AL {'checksub'}; | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  | sub suffix { | 
| 154 | 0 |  |  | 0 | 1 | 0 | shift if __PACKAGE__ || $_[0] eq (caller(0))[0]; | 
| 155 | 0 | 0 |  |  |  | 0 | $AL {'suffix'} = shift if @_; | 
| 156 | 0 |  |  |  |  | 0 | $AL {'suffix'}; | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  | # default check subroutine | 
| 159 |  |  |  |  |  |  | checksub ( __PACKAGE__, sub { (stat $_[0]) [9] } ); | 
| 160 |  |  |  |  |  |  | # default is not checking | 
| 161 |  |  |  |  |  |  | check    ( __PACKAGE__,  0); | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | # gensub - returns an anonymous subroutine. | 
| 164 |  |  |  |  |  |  | # Parameters: | 
| 165 |  |  |  |  |  |  | # if one:  filename (full path) | 
| 166 |  |  |  |  |  |  | # if more: package, filename [, checkfuncref [, auto ]] | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | sub gensub { | 
| 169 | 16 | 50 |  | 16 | 0 | 51 | my $package = scalar(@_) == 1 ? caller : shift; | 
| 170 | 16 |  |  |  |  | 24 | my $file    = shift; | 
| 171 | 16 |  | 33 |  |  | 65 | my $chkfunc = shift || $AL {'checksub'}; | 
| 172 | 16 |  | 50 |  |  | 46 | my $auto    = shift || $AL {'auto'} || 'auto'; | 
| 173 | 16 |  |  |  |  | 21 | my $function; | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | { | 
| 176 | 16 |  |  |  |  | 17 | ($function = pop (@{[ File::Spec->splitpath($file) ]}) ) =~ s/\..*//; | 
|  | 16 |  |  |  |  | 20 |  | 
|  | 16 |  |  |  |  | 246 |  | 
| 177 |  |  |  |  |  |  |  | 
| 178 | 16 | 50 | 50 |  |  | 101 | $file .= $AL {'suffix'} || '.al' unless $file =~ /\.\w+$/; | 
| 179 | 16 | 50 |  |  |  | 326 | unless (-e $file) { | 
| 180 | 16 |  |  |  |  | 39 | my ($filename, $seen); | 
| 181 |  |  |  |  |  |  | { | 
| 182 | 16 |  |  |  |  | 25 | $filename = File::Spec -> catfile ($auto, $package, $file); | 
|  | 23 |  |  |  |  | 222 |  | 
| 183 | 23 |  |  |  |  | 76 | foreach my $d ('.',@INC) { # check current working dir first | 
| 184 | 198 |  |  |  |  | 1324 | my $f = File::Spec -> catfile ($d,$filename); | 
| 185 | 198 | 100 |  |  |  | 2227 | if (-e $f) { | 
| 186 | 10 |  |  |  |  | 29 | $file = $f; | 
| 187 | 10 |  |  |  |  | 23 | last; | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  | } | 
| 190 | 23 | 100 |  |  |  | 48 | last if $seen; | 
| 191 | 16 | 100 |  |  |  | 182 | unless (-e $file) { | 
| 192 |  |  |  |  |  |  | # redo the search with a truncated filename | 
| 193 | 7 |  |  |  |  | 22 | $file =~ s/(\w{12,})(\.\w+)$/substr($1,0,11).$2/e; | 
|  | 1 |  |  |  |  | 7 |  | 
| 194 | 7 |  |  |  |  | 11 | $seen++; | 
| 195 | 7 |  |  |  |  | 11 | redo; | 
| 196 |  |  |  |  |  |  | } | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  | die | 
| 199 | 16 | 100 |  |  |  | 273 | "Can't locate function file '$filename' for package '$package'\n" | 
| 200 |  |  |  |  |  |  | unless -e $file; | 
| 201 |  |  |  |  |  |  | } | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 10 | 100 |  |  |  | 67 | if (my $addr = $AL {'Inc'} -> {"$package\::$function"} ) { | 
| 205 | 1 |  |  |  |  | 8 | return $AL {Sub} -> {$addr} -> {'outer'}; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | else { | 
| 208 |  |  |  |  |  |  | # file not known yet | 
| 209 | 9 |  |  |  |  | 14 | my $inner; | 
| 210 | 9 |  |  |  |  | 15 | my $h        = {}; | 
| 211 | 9 |  |  |  |  | 28 | my $cr       = $chkfunc -> ($file); | 
| 212 | 9 |  |  |  |  | 34 | my $subname  = "$package\::$function"; | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | $h = { | 
| 215 |  |  |  |  |  |  | file     => $file, | 
| 216 | 9 |  |  |  |  | 56 | check    => \$AL {'check'}, | 
| 217 |  |  |  |  |  |  | checksub => \$chkfunc, | 
| 218 |  |  |  |  |  |  | checkref => \$cr, | 
| 219 |  |  |  |  |  |  | function => $subname, | 
| 220 |  |  |  |  |  |  | }; | 
| 221 |  |  |  |  |  |  |  | 
| 222 | 9 | 100 |  |  |  | 28 | my $outer          = load ($package, $file, $h) or die $@; | 
| 223 | 8 |  |  |  |  | 29 | my $outeraddr      = Scalar::Util::refaddr ($outer); | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 8 |  |  |  |  | 14 | $h -> {'outer'} = $outer; | 
| 226 | 8 |  |  |  |  | 27 | Scalar::Util::weaken ($h -> {'outer'}); | 
| 227 |  |  |  |  |  |  |  | 
| 228 | 8 |  |  |  |  | 24 | $AL{Sub} -> {$outeraddr} = $h; | 
| 229 | 8 |  |  |  |  | 21 | $AL{Inc} -> {$subname}   = $outeraddr; | 
| 230 | 8 |  |  |  |  | 51 | return bless $outer, __PACKAGE__; | 
| 231 |  |  |  |  |  |  | } | 
| 232 |  |  |  |  |  |  | }; | 
| 233 |  |  |  |  |  |  | { | 
| 234 |  |  |  |  |  |  | my $load = \&load; | 
| 235 |  |  |  |  |  |  | sub load { | 
| 236 | 14 |  |  | 14 | 0 | 45 | my ($package, $file, $h) = @_; | 
| 237 | 14 |  |  |  |  | 66 | delete $INC {$file}; | 
| 238 | 14 |  |  |  |  | 1030 | my $ref = eval "package $package; require '$file'"; | 
| 239 |  |  |  |  |  |  | #warn $@ if $@; | 
| 240 | 14 | 100 |  |  |  | 196 | return undef if $@; | 
| 241 |  |  |  |  |  |  | { | 
| 242 |  |  |  |  |  |  | # just in case the require dinn' return a ref - | 
| 243 |  |  |  |  |  |  | # then a named subroutine has been loaded. | 
| 244 |  |  |  |  |  |  | # All other cases are errors. | 
| 245 | 13 | 100 | 66 |  |  | 25 | unless ( | 
|  | 13 |  |  |  |  | 99 |  | 
| 246 |  |  |  |  |  |  | Scalar::Util::reftype($ref) | 
| 247 |  |  |  |  |  |  | and | 
| 248 |  |  |  |  |  |  | Scalar::Util::reftype($ref) eq 'CODE') { | 
| 249 | 5 |  |  |  |  | 7 | $ref = \&{$h -> {'function'}}; | 
|  | 5 |  |  |  |  | 16 |  | 
| 250 | 4 |  |  | 4 |  | 32 | no strict 'refs'; | 
|  | 4 |  |  |  |  | 8 |  | 
|  | 4 |  |  |  |  | 150 |  | 
| 251 | 4 |  |  | 4 |  | 22 | no warnings 'redefine'; | 
|  | 4 |  |  |  |  | 8 |  | 
|  | 4 |  |  |  |  | 1310 |  | 
| 252 | 5 | 50 |  |  |  | 12 | *{$h -> {'function'} } = $h ->{'outer'} if $h -> {'outer'}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 253 |  |  |  |  |  |  | } | 
| 254 | 13 |  |  |  |  | 21 | ${$h->{inner}} = $ref; | 
|  | 13 |  |  |  |  | 55 |  | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | my $sub = sub { | 
| 257 | 22 |  |  | 22 |  | 2021411 | my $cr = $h -> {'checkref'}; | 
| 258 | 22 | 100 | 66 |  |  | 38 | if( ${ $h -> {'check'} } and ${ $h-> {'checksub'} } | 
|  | 22 |  | 100 |  |  | 114 |  | 
|  | 6 |  |  |  |  | 36 |  | 
| 259 |  |  |  |  |  |  | and | 
| 260 | 6 |  |  |  |  | 21 | ( my $c = ${ $h->{checksub} } -> ($file) ) != $$cr) { | 
| 261 | 5 | 50 |  |  |  | 86 | warn "reloading $file" if $Debug; | 
| 262 | 5 |  |  |  |  | 24 | $$cr = $c; | 
| 263 | 5 |  |  |  |  | 22 | $load -> ($package, $file, $h); | 
| 264 |  |  |  |  |  |  | } | 
| 265 | 22 |  |  |  |  | 97 | goto ${ $h -> {'inner'} }; | 
|  | 22 |  |  |  |  | 91 |  | 
| 266 | 13 |  |  |  |  | 92 | }; | 
| 267 |  |  |  |  |  |  | } | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | sub DESTROY { | 
| 272 | 2 |  |  | 2 |  | 747 | my $outeraddr = Scalar::Util::refaddr ($_[0]); | 
| 273 | 2 |  |  |  |  | 7 | my $h = $AL {'Sub'} -> {$outeraddr}; | 
| 274 | 2 |  |  |  |  | 9 | delete  $AL {'Inc'} -> { $h -> {'function'}}; | 
| 275 | 2 |  |  |  |  | 178 | delete  $AL {'Sub'} -> {$outeraddr}; | 
| 276 |  |  |  |  |  |  | } | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 279 | 4 |  |  | 4 |  | 31 | no strict; | 
|  | 4 |  |  |  |  | 5 |  | 
|  | 4 |  |  |  |  | 735 |  | 
| 280 | 10 |  |  | 10 |  | 3072 | my $sub = $AUTOLOAD; | 
| 281 | 10 |  |  |  |  | 18 | my ($pkg, $func, $filename); | 
| 282 |  |  |  |  |  |  | { | 
| 283 | 10 |  |  |  |  | 13 | ($pkg, $func) = ($sub =~ /(.*)::([^:]+)$/); | 
|  | 10 |  |  |  |  | 115 |  | 
| 284 | 10 |  |  |  |  | 102 | $pkg = File::Spec -> catdir (split /::/, $pkg); | 
| 285 |  |  |  |  |  |  | } | 
| 286 | 10 |  |  |  |  | 23 | my $save = $@; | 
| 287 | 10 |  |  |  |  | 48 | local $!; # Do not munge the value. | 
| 288 | 10 |  |  |  |  | 17 | my $ref; | 
| 289 | 10 |  | 100 |  |  | 12 | eval { local $SIG{__DIE__}; $ref = gensub ($pkg, $func, '', $AL{'auto'} || 'auto'); }; | 
|  | 10 |  |  |  |  | 35 |  | 
|  | 10 |  |  |  |  | 57 |  | 
| 290 | 10 | 100 |  |  |  | 29 | if ($@) { | 
| 291 | 4 | 100 |  |  |  | 14 | if (substr ($sub,-9) eq '::DESTROY') { | 
| 292 | 4 |  |  | 4 |  | 28 | no strict 'refs'; | 
|  | 4 |  |  |  |  | 7 |  | 
|  | 4 |  |  |  |  | 486 |  | 
| 293 | 2 |  |  | 0 |  | 17 | *$sub = sub {}; | 
| 294 | 2 |  |  |  |  | 4 | $@ = undef; | 
| 295 |  |  |  |  |  |  | } | 
| 296 | 4 | 100 |  |  |  | 9 | if ($@){ | 
| 297 | 2 |  |  |  |  | 3 | my $error = $@; | 
| 298 | 2 |  |  |  |  | 23 | require Carp; | 
| 299 | 2 |  |  |  |  | 232 | Carp::croak($error); | 
| 300 |  |  |  |  |  |  | } | 
| 301 |  |  |  |  |  |  | } | 
| 302 | 8 |  |  |  |  | 14 | $@ = $save; | 
| 303 | 8 | 100 |  |  |  | 37 | return unless $ref; | 
| 304 | 4 |  |  | 4 |  | 49 | no warnings 'redefine'; | 
|  | 4 |  |  |  |  | 8 |  | 
|  | 4 |  |  |  |  | 570 |  | 
| 305 | 6 |  |  |  |  | 20 | *$AUTOLOAD = $ref; | 
| 306 | 6 |  |  |  |  | 30 | goto $ref; | 
| 307 |  |  |  |  |  |  | } | 
| 308 |  |  |  |  |  |  |  | 
| 309 |  |  |  |  |  |  | # below are shameless plugs from AutoLoader 5.63 | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | sub import { | 
| 312 | 7 |  |  | 7 |  | 1934 | my $pkg     = shift; | 
| 313 | 7 |  |  |  |  | 16 | my $callpkg = caller; | 
| 314 | 7 | 50 |  |  |  | 27 | if ($pkg eq 'AutoReloader') { | 
| 315 | 7 | 100 | 66 |  |  | 67 | if ( @_ and $_[0] =~ /^&?AUTOLOAD$/ ) { | 
| 316 | 4 |  |  | 4 |  | 27 | no strict 'refs'; | 
|  | 4 |  |  |  |  | 22 |  | 
|  | 4 |  |  |  |  | 406 |  | 
| 317 | 4 |  |  |  |  | 12 | *{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD; | 
|  | 4 |  |  |  |  | 22 |  | 
| 318 | 4 |  |  |  |  | 10 | *{ $callpkg . '::can'      } = \&can; | 
|  | 4 |  |  |  |  | 1665 |  | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  | } | 
| 321 |  |  |  |  |  |  | } | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | sub unimport { | 
| 324 | 2 |  |  | 2 |  | 605 | my $callpkg = caller; | 
| 325 |  |  |  |  |  |  |  | 
| 326 | 4 |  |  | 4 |  | 27 | no strict 'refs'; | 
|  | 4 |  |  |  |  | 6 |  | 
|  | 4 |  |  |  |  | 796 |  | 
| 327 |  |  |  |  |  |  |  | 
| 328 | 2 |  |  |  |  | 6 | for my $exported (qw( AUTOLOAD can )) { | 
| 329 | 4 |  |  |  |  | 7 | my $symname = $callpkg . '::' . $exported; | 
| 330 | 4 | 100 |  |  |  | 4 | undef *{ $symname } if \&{ $symname } == \&{ $exported }; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 4 |  |  |  |  | 12 |  | 
|  | 4 |  |  |  |  | 15 |  | 
| 331 | 4 |  |  |  |  | 7 | *{ $symname } = \&{ $symname }; | 
|  | 4 |  |  |  |  | 18 |  | 
|  | 4 |  |  |  |  | 6 |  | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  | } | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | sub can { | 
| 336 | 5 |  |  | 5 | 0 | 742 | my ($self, $func) = @_; | 
| 337 | 5 |  |  |  |  | 28 | my $parent        = $self->SUPER::can( $func ); | 
| 338 | 5 | 100 |  |  |  | 14 | return $parent if $parent; | 
| 339 | 4 |  | 33 |  |  | 11 | my $pkg           = ref( $self ) || $self; | 
| 340 | 4 |  |  |  |  | 6 | local $@; | 
| 341 | 4 |  |  |  |  | 5 | my $ref; | 
| 342 | 4 | 100 | 50 |  |  | 6 | $ref = eval { local $SIG{__DIE__}; $ref = gensub ($pkg, $func, '', $AL{'auto'} || 'auto'); } | 
|  | 4 |  |  |  |  | 14 |  | 
|  | 4 |  |  |  |  | 20 |  | 
| 343 |  |  |  |  |  |  | or return undef; | 
| 344 | 4 |  |  | 4 |  | 29 | no strict 'refs'; | 
|  | 4 |  |  |  |  | 8 |  | 
|  | 4 |  |  |  |  | 132 |  | 
| 345 | 4 |  |  | 4 |  | 30 | no warnings 'redefine'; | 
|  | 4 |  |  |  |  | 15 |  | 
|  | 4 |  |  |  |  | 304 |  | 
| 346 | 1 |  |  |  |  | 2 | *{ $pkg . '::' . $func } = $ref; | 
|  | 1 |  |  |  |  | 5 |  | 
| 347 | 1 |  |  |  |  | 3 | $ref; | 
| 348 |  |  |  |  |  |  | } | 
| 349 |  |  |  |  |  |  | 1; | 
| 350 |  |  |  |  |  |  | __END__ |