This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Allow specifying a comparison function for Search::Dict::look().
[perl5.git] / lib / AutoLoader.pm
index 666c6ca..4b2261e 100644 (file)
@@ -1,20 +1,27 @@
 package AutoLoader;
 
-use vars qw(@EXPORT @EXPORT_OK);
+use 5.6.0;
+our(@EXPORT, @EXPORT_OK, $VERSION);
 
 my $is_dosish;
+my $is_epoc;
 my $is_vms;
+my $is_macos;
 
 BEGIN {
     require Exporter;
-    @EXPORT = ();
-    @EXPORT_OK = qw(AUTOLOAD);
-    $is_dosish = $^O eq 'dos' || $^O eq 'os2' || $^O eq 'MSWin32';
+    @EXPORT = @EXPORT = ();
+    @EXPORT_OK = @EXPORT_OK = qw(AUTOLOAD);
+    $is_dosish = $^O eq 'dos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'NetWare';
+    $is_epoc = $^O eq 'epoc';
     $is_vms = $^O eq 'VMS';
+    $is_macos = $^O eq 'MacOS';
+    $VERSION = '5.58';
 }
 
 AUTOLOAD {
-    my $name;
+    my $sub = $AUTOLOAD;
+    my $filename;
     # Braces used to preserve $1 et al.
     {
        # Try to find the autoloaded file from the package-qualified
@@ -30,10 +37,15 @@ AUTOLOAD {
        # In this case, we simple prepend the 'auto/' and let the
        # C<require> take care of the searching for us.
 
-       my ($pkg,$func) = $AUTOLOAD =~ /(.*)::([^:]+)$/;
+       my ($pkg,$func) = ($sub =~ /(.*)::([^:]+)$/);
        $pkg =~ s#::#/#g;
-       if (defined($name=$INC{"$pkg.pm"})) {
-           $name =~ s#^(.*)$pkg\.pm$#$1auto/$pkg/$func.al#;
+       if (defined($filename = $INC{"$pkg.pm"})) {
+           if ($is_macos) {
+               $pkg =~ tr#/#:#;
+               $filename =~ s#^(.*)$pkg\.pm\z#$1auto:$pkg:$func.al#s;
+           } else {
+               $filename =~ s#^(.*)$pkg\.pm\z#$1auto/$pkg/$func.al#s;
+           }
 
            # if the file exists, then make sure that it is a
            # a fully anchored path (i.e either '/usr/lib/auto/foo/bar.al',
@@ -41,45 +53,55 @@ AUTOLOAD {
            # (and failing) to find the 'lib/auto/foo/bar.al' because it
            # looked for 'lib/lib/auto/foo/bar.al', given @INC = ('lib').
 
-           if (-r $name) {
-               unless ($name =~ m|^/|) {
+           if (-r $filename) {
+               unless ($filename =~ m|^/|s) {
                    if ($is_dosish) {
-                       unless ($name =~ m{^([a-z]:)?[\\/]}i) {
-                            $name = "./$name";
+                       unless ($filename =~ m{^([a-z]:)?[\\/]}is) {
+                            if ($^O ne 'NetWare') {
+                                       $filename = "./$filename";
+                               } else {
+                                       $filename = "$filename";
+                               }
+                       }
+                   }
+                   elsif ($is_epoc) {
+                       unless ($filename =~ m{^([a-z?]:)?[\\/]}is) {
+                            $filename = "./$filename";
                        }
                    }
                    elsif ($is_vms) {
-                       # XXX todo by VMSmiths
-                       $name = "./$name";
+                       # XXX todo by VMSmiths
+                       $filename = "./$filename";
                    }
-                   else {
-                       $name = "./$name";
+                   elsif (!$is_macos) {
+                       $filename = "./$filename";
                    }
                }
            }
            else {
-               $name = undef;
+               $filename = undef;
            }
        }
-       unless (defined $name) {
+       unless (defined $filename) {
            # let C<require> do the searching
-           $name = "auto/$AUTOLOAD.al";
-           $name =~ s#::#/#g;
+           $filename = "auto/$sub.al";
+           $filename =~ s#::#/#g;
        }
     }
     my $save = $@;
-    eval { local $SIG{__DIE__}; require $name };
+    local $!; # Do not munge the value. 
+    eval { local $SIG{__DIE__}; require $filename };
     if ($@) {
-       if (substr($AUTOLOAD,-9) eq '::DESTROY') {
-           *$AUTOLOAD = sub {};
+       if (substr($sub,-9) eq '::DESTROY') {
+           *$sub = sub {};
        } else {
            # The load might just have failed because the filename was too
            # long for some old SVR3 systems which treat long names as errors.
            # If we can succesfully truncate a long name then it's worth a go.
            # There is a slight risk that we could pick up the wrong file here
            # but autosplit should have warned about that when splitting.
-           if ($name =~ s/(\w{12,})\.al$/substr($1,0,11).".al"/e){
-               eval {local $SIG{__DIE__};require $name};
+           if ($filename =~ s/(\w{12,})\.al$/substr($1,0,11).".al"/e){
+               eval { local $SIG{__DIE__}; require $filename };
            }
            if ($@){
                $@ =~ s/ at .*\n//;
@@ -90,7 +112,7 @@ AUTOLOAD {
        }
     }
     $@ = $save;
-    goto &$AUTOLOAD;
+    goto &$sub;
 }
 
 sub import {
@@ -101,7 +123,10 @@ sub import {
     # Export symbols, but not by accident of inheritance.
     #
 
-    Exporter::export $pkg, $callpkg, @_ if $pkg eq 'AutoLoader';
+    if ($pkg eq 'AutoLoader') {
+      local $Exporter::ExportLevel = 1;
+      Exporter::import $pkg, @_;
+    }
 
     #
     # Try to find the autosplit index file.  Eg., if the call package
@@ -119,7 +144,13 @@ sub import {
     my $path = $INC{$calldir . '.pm'};
     if (defined($path)) {
        # Try absolute path name.
-       $path =~ s#^(.*)$calldir\.pm$#$1auto/$calldir/autosplit.ix#;
+       if ($is_macos) {
+           (my $malldir = $calldir) =~ tr#/#:#;
+           $path =~ s#^(.*)$malldir\.pm\z#$1auto:$malldir:autosplit.ix#s;
+       } else {
+           $path =~ s#^(.*)$calldir\.pm\z#$1auto/$calldir/autosplit.ix#;
+       }
+
        eval { require $path; };
        # If that failed, try relative path with normal @INC searching.
        if ($@) {
@@ -134,6 +165,11 @@ sub import {
     } 
 }
 
+sub unimport {
+  my $callpkg = caller;
+  eval "package $callpkg; sub AUTOLOAD;";
+}
+
 1;
 
 __END__
@@ -178,7 +214,7 @@ such a file exists, AUTOLOAD will read and evaluate it,
 thus (presumably) defining the needed subroutine.  AUTOLOAD will then
 C<goto> the newly defined subroutine.
 
-Once this process completes for a given funtion, it is defined, so
+Once this process completes for a given function, it is defined, so
 future calls to the subroutine will bypass the AUTOLOAD mechanism.
 
 =head2 Subroutine Stubs
@@ -219,20 +255,20 @@ lines:
     use Carp;
 
     sub AUTOLOAD {
-        my $constname;
-        ($constname = $AUTOLOAD) =~ s/.*:://;
+        my $sub = $AUTOLOAD;
+        (my $constname = $sub) =~ s/.*:://;
         my $val = constant($constname, @_ ? $_[0] : 0);
         if ($! != 0) {
-            if ($! =~ /Invalid/) {
-                $AutoLoader::AUTOLOAD = $AUTOLOAD;
+            if ($! =~ /Invalid/ || $!{EINVAL}) {
+                $AutoLoader::AUTOLOAD = $sub;
                 goto &AutoLoader::AUTOLOAD;
             }
             else {
                 croak "Your vendor has not defined constant $constname";
             }
         }
-       *$AUTOLOAD = sub { $val }; # same as: eval "sub $AUTOLOAD { $val }";
-        goto &$AUTOLOAD;
+        *$sub = sub { $val }; # same as: eval "sub $sub { $val }";
+        goto &$sub;
     }
 
 If any module's own AUTOLOAD subroutine has no need to fallback to the
@@ -253,6 +289,12 @@ the package namespace.  Variables pre-declared with this pragma will be
 visible to any autoloaded routines (but will not be invisible outside
 the package, unfortunately).
 
+=head2 Not Using AutoLoader
+
+You can stop using AutoLoader by simply
+
+       no AutoLoader;
+
 =head2 B<AutoLoader> vs. B<SelfLoader>
 
 The B<AutoLoader> is similar in purpose to B<SelfLoader>: both delay the
@@ -266,7 +308,7 @@ C<__DATA__>, after which routines are cached.  B<SelfLoader> can also
 handle multiple packages in a file.
 
 B<AutoLoader> only reads code as it is requested, and in many cases
-should be faster, but requires a machanism like B<AutoSplit> be used to
+should be faster, but requires a mechanism like B<AutoSplit> be used to
 create the individual files.  L<ExtUtils::MakeMaker> will invoke
 B<AutoSplit> automatically if B<AutoLoader> is used in a module source
 file.