perlfunc: update require() pseudocode
authorDavid Mitchell <davem@iabyn.com>
Tue, 5 Nov 2013 15:52:31 +0000 (15:52 +0000)
committerDavid Mitchell <davem@iabyn.com>
Tue, 5 Nov 2013 16:14:57 +0000 (16:14 +0000)
RT #120292

The entry for require() in perlfunc has a perl function that's supposed to
illustrate how require works is rather out of date. In particular, the
fact that the search stops on EACCES wasn't incorporated, and the various
ways of it failing and reporting errors was inaccurate.

I also removed the explicit code for executing the 'do' in the caller's
package, and replaced it with just the comment 'but run in caller's
namespace', since the details were a bit obscure.

Finally, I re-indented it since it had strange 3-space indents

pod/perlfunc.pod

index 2434f89..0e608c9 100644 (file)
@@ -5787,45 +5787,44 @@ would have semantics similar to the following:
     use version;
 
     sub require {
-       my ($filename) = @_;
-       if ( my $version = eval { version->parse($filename) } ) {
-           if ( $version > $^V ) {
-               my $vn = $version->normal;
-               croak "Perl $vn required--this is only $^V, stopped";
-           }
-           return 1;
-       }
-       if (exists $INC{$filename}) {
-           return 1 if $INC{$filename};
-           croak "Compilation failed in require";
-       }
-       my ($realfilename,$result);
-       ITER: {
-           foreach $prefix (@INC) {
-               $realfilename = "$prefix/$filename";
-               if (-f $realfilename) {
-                   $INC{$filename} = $realfilename;
-                   my $caller = caller;
-                   my $do_as_caller = eval qq{
-                       package $caller;
-                       sub { do \$_[0] }
-                   };
-                   $result = $do_as_caller->($realfilename);
-                   last ITER;
-               }
-           }
-           croak "Can't locate $filename in \@INC";
-       }
-       if ($@) {
-           $INC{$filename} = undef;
-           croak $@;
-       } elsif (!$result) {
-           delete $INC{$filename};
-           croak "$filename did not return true value";
-       } else {
-           $! = 0;
-           return $result;
-       }
+        my ($filename) = @_;
+        if ( my $version = eval { version->parse($filename) } ) {
+            if ( $version > $^V ) {
+                my $vn = $version->normal;
+                croak "Perl $vn required--this is only $^V, stopped";
+            }
+            return 1;
+        }
+
+        if (exists $INC{$filename}) {
+            return 1 if $INC{$filename};
+            croak "Compilation failed in require";
+        }
+
+        foreach $prefix (@INC) {
+            if (ref($prefix)) {
+                #... do other stuff - see text below ....
+            }
+            # (see text below about possible appending of .pmc
+            # suffix to $filename)
+            my $realfilename = "$prefix/$filename";
+            next if ! -e $realfilename || -d _ || -b _;
+            $INC{$filename} = $realfilename;
+            my $result = do($realfilename); # but run in caller's namespace
+
+            if (!defined $result) {
+                $INC{$filename} = undef;
+                croak $@ ? "$@Compilation failed in require"
+                         : "Can't locate $filename: $!\n";
+            }
+            if (!$result) {
+                delete $INC{$filename};
+                croak "$filename did not return true value";
+            }
+            $! = 0;
+            return $result;
+        }
+        croak "Can't locate $filename in \@INC ...";
     }
 
 Note that the file will not be included twice under the same specified