blob: 9b1a901503c75fca5e12517fa8e7e8d180b255a3 [file] [log] [blame]
Rashed Abdel-Tawab4db47f42019-09-06 10:38:22 -07001package AutoLoader;
2
3use strict;
4use 5.006_001;
5
6our($VERSION, $AUTOLOAD);
7
8my $is_dosish;
9my $is_epoc;
10my $is_vms;
11my $is_macos;
12
13BEGIN {
14 $is_dosish = $^O eq 'dos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'NetWare';
15 $is_epoc = $^O eq 'epoc';
16 $is_vms = $^O eq 'VMS';
17 $is_macos = $^O eq 'MacOS';
18 $VERSION = '5.74';
19}
20
21AUTOLOAD {
22 my $sub = $AUTOLOAD;
23 autoload_sub($sub);
24 goto &$sub;
25}
26
27sub autoload_sub {
28 my $sub = shift;
29
30 my $filename = AutoLoader::find_filename( $sub );
31
32 my $save = $@;
33 local $!; # Do not munge the value.
34 eval { local $SIG{__DIE__}; require $filename };
35 if ($@) {
36 if (substr($sub,-9) eq '::DESTROY') {
37 no strict 'refs';
38 *$sub = sub {};
39 $@ = undef;
40 } elsif ($@ =~ /^Can't locate/) {
41 # The load might just have failed because the filename was too
42 # long for some old SVR3 systems which treat long names as errors.
43 # If we can successfully truncate a long name then it's worth a go.
44 # There is a slight risk that we could pick up the wrong file here
45 # but autosplit should have warned about that when splitting.
46 if ($filename =~ s/(\w{12,})\.al$/substr($1,0,11).".al"/e){
47 eval { local $SIG{__DIE__}; require $filename };
48 }
49 }
50 if ($@){
51 $@ =~ s/ at .*\n//;
52 my $error = $@;
53 require Carp;
54 Carp::croak($error);
55 }
56 }
57 $@ = $save;
58
59 return 1;
60}
61
62sub find_filename {
63 my $sub = shift;
64 my $filename;
65 # Braces used to preserve $1 et al.
66 {
67 # Try to find the autoloaded file from the package-qualified
68 # name of the sub. e.g., if the sub needed is
69 # Getopt::Long::GetOptions(), then $INC{Getopt/Long.pm} is
70 # something like '/usr/lib/perl5/Getopt/Long.pm', and the
71 # autoload file is '/usr/lib/perl5/auto/Getopt/Long/GetOptions.al'.
72 #
73 # However, if @INC is a relative path, this might not work. If,
74 # for example, @INC = ('lib'), then $INC{Getopt/Long.pm} is
75 # 'lib/Getopt/Long.pm', and we want to require
76 # 'auto/Getopt/Long/GetOptions.al' (without the leading 'lib').
77 # In this case, we simple prepend the 'auto/' and let the
78 # C<require> take care of the searching for us.
79
80 my ($pkg,$func) = ($sub =~ /(.*)::([^:]+)$/);
81 $pkg =~ s#::#/#g;
82 if (defined($filename = $INC{"$pkg.pm"})) {
83 if ($is_macos) {
84 $pkg =~ tr#/#:#;
85 $filename = undef
86 unless $filename =~ s#^(.*)$pkg\.pm\z#$1auto:$pkg:$func.al#s;
87 } else {
88 $filename = undef
89 unless $filename =~ s#^(.*)$pkg\.pm\z#$1auto/$pkg/$func.al#s;
90 }
91
92 # if the file exists, then make sure that it is a
93 # a fully anchored path (i.e either '/usr/lib/auto/foo/bar.al',
94 # or './lib/auto/foo/bar.al'. This avoids C<require> searching
95 # (and failing) to find the 'lib/auto/foo/bar.al' because it
96 # looked for 'lib/lib/auto/foo/bar.al', given @INC = ('lib').
97
98 if (defined $filename and -r $filename) {
99 unless ($filename =~ m|^/|s) {
100 if ($is_dosish) {
101 unless ($filename =~ m{^([a-z]:)?[\\/]}is) {
102 if ($^O ne 'NetWare') {
103 $filename = "./$filename";
104 } else {
105 $filename = "$filename";
106 }
107 }
108 }
109 elsif ($is_epoc) {
110 unless ($filename =~ m{^([a-z?]:)?[\\/]}is) {
111 $filename = "./$filename";
112 }
113 }
114 elsif ($is_vms) {
115 # XXX todo by VMSmiths
116 $filename = "./$filename";
117 }
118 elsif (!$is_macos) {
119 $filename = "./$filename";
120 }
121 }
122 }
123 else {
124 $filename = undef;
125 }
126 }
127 unless (defined $filename) {
128 # let C<require> do the searching
129 $filename = "auto/$sub.al";
130 $filename =~ s#::#/#g;
131 }
132 }
133 return $filename;
134}
135
136sub import {
137 my $pkg = shift;
138 my $callpkg = caller;
139
140 #
141 # Export symbols, but not by accident of inheritance.
142 #
143
144 if ($pkg eq 'AutoLoader') {
145 if ( @_ and $_[0] =~ /^&?AUTOLOAD$/ ) {
146 no strict 'refs';
147 *{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD;
148 }
149 }
150
151 #
152 # Try to find the autosplit index file. Eg., if the call package
153 # is POSIX, then $INC{POSIX.pm} is something like
154 # '/usr/local/lib/perl5/POSIX.pm', and the autosplit index file is in
155 # '/usr/local/lib/perl5/auto/POSIX/autosplit.ix', so we require that.
156 #
157 # However, if @INC is a relative path, this might not work. If,
158 # for example, @INC = ('lib'), then
159 # $INC{POSIX.pm} is 'lib/POSIX.pm', and we want to require
160 # 'auto/POSIX/autosplit.ix' (without the leading 'lib').
161 #
162
163 (my $calldir = $callpkg) =~ s#::#/#g;
164 my $path = $INC{$calldir . '.pm'};
165 if (defined($path)) {
166 # Try absolute path name, but only eval it if the
167 # transformation from module path to autosplit.ix path
168 # succeeded!
169 my $replaced_okay;
170 if ($is_macos) {
171 (my $malldir = $calldir) =~ tr#/#:#;
172 $replaced_okay = ($path =~ s#^(.*)$malldir\.pm\z#$1auto:$malldir:autosplit.ix#s);
173 } else {
174 $replaced_okay = ($path =~ s#^(.*)$calldir\.pm\z#$1auto/$calldir/autosplit.ix#);
175 }
176
177 eval { require $path; } if $replaced_okay;
178 # If that failed, try relative path with normal @INC searching.
179 if (!$replaced_okay or $@) {
180 $path ="auto/$calldir/autosplit.ix";
181 eval { require $path; };
182 }
183 if ($@) {
184 my $error = $@;
185 require Carp;
186 Carp::carp($error);
187 }
188 }
189}
190
191sub unimport {
192 my $callpkg = caller;
193
194 no strict 'refs';
195
196 for my $exported (qw( AUTOLOAD )) {
197 my $symname = $callpkg . '::' . $exported;
198 undef *{ $symname } if \&{ $symname } == \&{ $exported };
199 *{ $symname } = \&{ $symname };
200 }
201}
202
2031;
204
205__END__
206