xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/AutoLoader.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gatepackage AutoLoader;
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gateuse strict;
4*0Sstevel@tonic-gateuse 5.006_001;
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gateour($VERSION, $AUTOLOAD);
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gatemy $is_dosish;
9*0Sstevel@tonic-gatemy $is_epoc;
10*0Sstevel@tonic-gatemy $is_vms;
11*0Sstevel@tonic-gatemy $is_macos;
12*0Sstevel@tonic-gate
13*0Sstevel@tonic-gateBEGIN {
14*0Sstevel@tonic-gate    $is_dosish = $^O eq 'dos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'NetWare';
15*0Sstevel@tonic-gate    $is_epoc = $^O eq 'epoc';
16*0Sstevel@tonic-gate    $is_vms = $^O eq 'VMS';
17*0Sstevel@tonic-gate    $is_macos = $^O eq 'MacOS';
18*0Sstevel@tonic-gate    $VERSION = '5.60';
19*0Sstevel@tonic-gate}
20*0Sstevel@tonic-gate
21*0Sstevel@tonic-gateAUTOLOAD {
22*0Sstevel@tonic-gate    my $sub = $AUTOLOAD;
23*0Sstevel@tonic-gate    my $filename;
24*0Sstevel@tonic-gate    # Braces used to preserve $1 et al.
25*0Sstevel@tonic-gate    {
26*0Sstevel@tonic-gate	# Try to find the autoloaded file from the package-qualified
27*0Sstevel@tonic-gate	# name of the sub. e.g., if the sub needed is
28*0Sstevel@tonic-gate	# Getopt::Long::GetOptions(), then $INC{Getopt/Long.pm} is
29*0Sstevel@tonic-gate	# something like '/usr/lib/perl5/Getopt/Long.pm', and the
30*0Sstevel@tonic-gate	# autoload file is '/usr/lib/perl5/auto/Getopt/Long/GetOptions.al'.
31*0Sstevel@tonic-gate	#
32*0Sstevel@tonic-gate	# However, if @INC is a relative path, this might not work.  If,
33*0Sstevel@tonic-gate	# for example, @INC = ('lib'), then $INC{Getopt/Long.pm} is
34*0Sstevel@tonic-gate	# 'lib/Getopt/Long.pm', and we want to require
35*0Sstevel@tonic-gate	# 'auto/Getopt/Long/GetOptions.al' (without the leading 'lib').
36*0Sstevel@tonic-gate	# In this case, we simple prepend the 'auto/' and let the
37*0Sstevel@tonic-gate	# C<require> take care of the searching for us.
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate	my ($pkg,$func) = ($sub =~ /(.*)::([^:]+)$/);
40*0Sstevel@tonic-gate	$pkg =~ s#::#/#g;
41*0Sstevel@tonic-gate	if (defined($filename = $INC{"$pkg.pm"})) {
42*0Sstevel@tonic-gate	    if ($is_macos) {
43*0Sstevel@tonic-gate		$pkg =~ tr#/#:#;
44*0Sstevel@tonic-gate		$filename =~ s#^(.*)$pkg\.pm\z#$1auto:$pkg:$func.al#s;
45*0Sstevel@tonic-gate	    } else {
46*0Sstevel@tonic-gate		$filename =~ s#^(.*)$pkg\.pm\z#$1auto/$pkg/$func.al#s;
47*0Sstevel@tonic-gate	    }
48*0Sstevel@tonic-gate
49*0Sstevel@tonic-gate	    # if the file exists, then make sure that it is a
50*0Sstevel@tonic-gate	    # a fully anchored path (i.e either '/usr/lib/auto/foo/bar.al',
51*0Sstevel@tonic-gate	    # or './lib/auto/foo/bar.al'.  This avoids C<require> searching
52*0Sstevel@tonic-gate	    # (and failing) to find the 'lib/auto/foo/bar.al' because it
53*0Sstevel@tonic-gate	    # looked for 'lib/lib/auto/foo/bar.al', given @INC = ('lib').
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate	    if (-r $filename) {
56*0Sstevel@tonic-gate		unless ($filename =~ m|^/|s) {
57*0Sstevel@tonic-gate		    if ($is_dosish) {
58*0Sstevel@tonic-gate			unless ($filename =~ m{^([a-z]:)?[\\/]}is) {
59*0Sstevel@tonic-gate			     if ($^O ne 'NetWare') {
60*0Sstevel@tonic-gate					$filename = "./$filename";
61*0Sstevel@tonic-gate				} else {
62*0Sstevel@tonic-gate					$filename = "$filename";
63*0Sstevel@tonic-gate				}
64*0Sstevel@tonic-gate			}
65*0Sstevel@tonic-gate		    }
66*0Sstevel@tonic-gate		    elsif ($is_epoc) {
67*0Sstevel@tonic-gate			unless ($filename =~ m{^([a-z?]:)?[\\/]}is) {
68*0Sstevel@tonic-gate			     $filename = "./$filename";
69*0Sstevel@tonic-gate			}
70*0Sstevel@tonic-gate		    }
71*0Sstevel@tonic-gate		    elsif ($is_vms) {
72*0Sstevel@tonic-gate			# XXX todo by VMSmiths
73*0Sstevel@tonic-gate			$filename = "./$filename";
74*0Sstevel@tonic-gate		    }
75*0Sstevel@tonic-gate		    elsif (!$is_macos) {
76*0Sstevel@tonic-gate			$filename = "./$filename";
77*0Sstevel@tonic-gate		    }
78*0Sstevel@tonic-gate		}
79*0Sstevel@tonic-gate	    }
80*0Sstevel@tonic-gate	    else {
81*0Sstevel@tonic-gate		$filename = undef;
82*0Sstevel@tonic-gate	    }
83*0Sstevel@tonic-gate	}
84*0Sstevel@tonic-gate	unless (defined $filename) {
85*0Sstevel@tonic-gate	    # let C<require> do the searching
86*0Sstevel@tonic-gate	    $filename = "auto/$sub.al";
87*0Sstevel@tonic-gate	    $filename =~ s#::#/#g;
88*0Sstevel@tonic-gate	}
89*0Sstevel@tonic-gate    }
90*0Sstevel@tonic-gate    my $save = $@;
91*0Sstevel@tonic-gate    local $!; # Do not munge the value.
92*0Sstevel@tonic-gate    eval { local $SIG{__DIE__}; require $filename };
93*0Sstevel@tonic-gate    if ($@) {
94*0Sstevel@tonic-gate	if (substr($sub,-9) eq '::DESTROY') {
95*0Sstevel@tonic-gate	    no strict 'refs';
96*0Sstevel@tonic-gate	    *$sub = sub {};
97*0Sstevel@tonic-gate	    $@ = undef;
98*0Sstevel@tonic-gate	} elsif ($@ =~ /^Can't locate/) {
99*0Sstevel@tonic-gate	    # The load might just have failed because the filename was too
100*0Sstevel@tonic-gate	    # long for some old SVR3 systems which treat long names as errors.
101*0Sstevel@tonic-gate	    # If we can successfully truncate a long name then it's worth a go.
102*0Sstevel@tonic-gate	    # There is a slight risk that we could pick up the wrong file here
103*0Sstevel@tonic-gate	    # but autosplit should have warned about that when splitting.
104*0Sstevel@tonic-gate	    if ($filename =~ s/(\w{12,})\.al$/substr($1,0,11).".al"/e){
105*0Sstevel@tonic-gate		eval { local $SIG{__DIE__}; require $filename };
106*0Sstevel@tonic-gate	    }
107*0Sstevel@tonic-gate	}
108*0Sstevel@tonic-gate	if ($@){
109*0Sstevel@tonic-gate	    $@ =~ s/ at .*\n//;
110*0Sstevel@tonic-gate	    my $error = $@;
111*0Sstevel@tonic-gate	    require Carp;
112*0Sstevel@tonic-gate	    Carp::croak($error);
113*0Sstevel@tonic-gate	}
114*0Sstevel@tonic-gate    }
115*0Sstevel@tonic-gate    $@ = $save;
116*0Sstevel@tonic-gate    goto &$sub;
117*0Sstevel@tonic-gate}
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gatesub import {
120*0Sstevel@tonic-gate    my $pkg = shift;
121*0Sstevel@tonic-gate    my $callpkg = caller;
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate    #
124*0Sstevel@tonic-gate    # Export symbols, but not by accident of inheritance.
125*0Sstevel@tonic-gate    #
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gate    if ($pkg eq 'AutoLoader') {
128*0Sstevel@tonic-gate	no strict 'refs';
129*0Sstevel@tonic-gate	*{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD
130*0Sstevel@tonic-gate	    if @_ and $_[0] =~ /^&?AUTOLOAD$/;
131*0Sstevel@tonic-gate    }
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate    #
134*0Sstevel@tonic-gate    # Try to find the autosplit index file.  Eg., if the call package
135*0Sstevel@tonic-gate    # is POSIX, then $INC{POSIX.pm} is something like
136*0Sstevel@tonic-gate    # '/usr/local/lib/perl5/POSIX.pm', and the autosplit index file is in
137*0Sstevel@tonic-gate    # '/usr/local/lib/perl5/auto/POSIX/autosplit.ix', so we require that.
138*0Sstevel@tonic-gate    #
139*0Sstevel@tonic-gate    # However, if @INC is a relative path, this might not work.  If,
140*0Sstevel@tonic-gate    # for example, @INC = ('lib'), then
141*0Sstevel@tonic-gate    # $INC{POSIX.pm} is 'lib/POSIX.pm', and we want to require
142*0Sstevel@tonic-gate    # 'auto/POSIX/autosplit.ix' (without the leading 'lib').
143*0Sstevel@tonic-gate    #
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gate    (my $calldir = $callpkg) =~ s#::#/#g;
146*0Sstevel@tonic-gate    my $path = $INC{$calldir . '.pm'};
147*0Sstevel@tonic-gate    if (defined($path)) {
148*0Sstevel@tonic-gate	# Try absolute path name.
149*0Sstevel@tonic-gate	if ($is_macos) {
150*0Sstevel@tonic-gate	    (my $malldir = $calldir) =~ tr#/#:#;
151*0Sstevel@tonic-gate	    $path =~ s#^(.*)$malldir\.pm\z#$1auto:$malldir:autosplit.ix#s;
152*0Sstevel@tonic-gate	} else {
153*0Sstevel@tonic-gate	    $path =~ s#^(.*)$calldir\.pm\z#$1auto/$calldir/autosplit.ix#;
154*0Sstevel@tonic-gate	}
155*0Sstevel@tonic-gate
156*0Sstevel@tonic-gate	eval { require $path; };
157*0Sstevel@tonic-gate	# If that failed, try relative path with normal @INC searching.
158*0Sstevel@tonic-gate	if ($@) {
159*0Sstevel@tonic-gate	    $path ="auto/$calldir/autosplit.ix";
160*0Sstevel@tonic-gate	    eval { require $path; };
161*0Sstevel@tonic-gate	}
162*0Sstevel@tonic-gate	if ($@) {
163*0Sstevel@tonic-gate	    my $error = $@;
164*0Sstevel@tonic-gate	    require Carp;
165*0Sstevel@tonic-gate	    Carp::carp($error);
166*0Sstevel@tonic-gate	}
167*0Sstevel@tonic-gate    }
168*0Sstevel@tonic-gate}
169*0Sstevel@tonic-gate
170*0Sstevel@tonic-gatesub unimport {
171*0Sstevel@tonic-gate    my $callpkg = caller;
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gate    no strict 'refs';
174*0Sstevel@tonic-gate    my $symname = $callpkg . '::AUTOLOAD';
175*0Sstevel@tonic-gate    undef *{ $symname } if \&{ $symname } == \&AUTOLOAD;
176*0Sstevel@tonic-gate    *{ $symname } = \&{ $symname };
177*0Sstevel@tonic-gate}
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gate1;
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate__END__
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate=head1 NAME
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gateAutoLoader - load subroutines only on demand
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate=head1 SYNOPSIS
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate    package Foo;
190*0Sstevel@tonic-gate    use AutoLoader 'AUTOLOAD';   # import the default AUTOLOAD subroutine
191*0Sstevel@tonic-gate
192*0Sstevel@tonic-gate    package Bar;
193*0Sstevel@tonic-gate    use AutoLoader;              # don't import AUTOLOAD, define our own
194*0Sstevel@tonic-gate    sub AUTOLOAD {
195*0Sstevel@tonic-gate        ...
196*0Sstevel@tonic-gate        $AutoLoader::AUTOLOAD = "...";
197*0Sstevel@tonic-gate        goto &AutoLoader::AUTOLOAD;
198*0Sstevel@tonic-gate    }
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate=head1 DESCRIPTION
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gateThe B<AutoLoader> module works with the B<AutoSplit> module and the
203*0Sstevel@tonic-gateC<__END__> token to defer the loading of some subroutines until they are
204*0Sstevel@tonic-gateused rather than loading them all at once.
205*0Sstevel@tonic-gate
206*0Sstevel@tonic-gateTo use B<AutoLoader>, the author of a module has to place the
207*0Sstevel@tonic-gatedefinitions of subroutines to be autoloaded after an C<__END__> token.
208*0Sstevel@tonic-gate(See L<perldata>.)  The B<AutoSplit> module can then be run manually to
209*0Sstevel@tonic-gateextract the definitions into individual files F<auto/funcname.al>.
210*0Sstevel@tonic-gate
211*0Sstevel@tonic-gateB<AutoLoader> implements an AUTOLOAD subroutine.  When an undefined
212*0Sstevel@tonic-gatesubroutine in is called in a client module of B<AutoLoader>,
213*0Sstevel@tonic-gateB<AutoLoader>'s AUTOLOAD subroutine attempts to locate the subroutine in a
214*0Sstevel@tonic-gatefile with a name related to the location of the file from which the
215*0Sstevel@tonic-gateclient module was read.  As an example, if F<POSIX.pm> is located in
216*0Sstevel@tonic-gateF</usr/local/lib/perl5/POSIX.pm>, B<AutoLoader> will look for perl
217*0Sstevel@tonic-gatesubroutines B<POSIX> in F</usr/local/lib/perl5/auto/POSIX/*.al>, where
218*0Sstevel@tonic-gatethe C<.al> file has the same name as the subroutine, sans package.  If
219*0Sstevel@tonic-gatesuch a file exists, AUTOLOAD will read and evaluate it,
220*0Sstevel@tonic-gatethus (presumably) defining the needed subroutine.  AUTOLOAD will then
221*0Sstevel@tonic-gateC<goto> the newly defined subroutine.
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gateOnce this process completes for a given function, it is defined, so
224*0Sstevel@tonic-gatefuture calls to the subroutine will bypass the AUTOLOAD mechanism.
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate=head2 Subroutine Stubs
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gateIn order for object method lookup and/or prototype checking to operate
229*0Sstevel@tonic-gatecorrectly even when methods have not yet been defined it is necessary to
230*0Sstevel@tonic-gate"forward declare" each subroutine (as in C<sub NAME;>).  See
231*0Sstevel@tonic-gateL<perlsub/"SYNOPSIS">.  Such forward declaration creates "subroutine
232*0Sstevel@tonic-gatestubs", which are place holders with no code.
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gateThe AutoSplit and B<AutoLoader> modules automate the creation of forward
235*0Sstevel@tonic-gatedeclarations.  The AutoSplit module creates an 'index' file containing
236*0Sstevel@tonic-gateforward declarations of all the AutoSplit subroutines.  When the
237*0Sstevel@tonic-gateAutoLoader module is 'use'd it loads these declarations into its callers
238*0Sstevel@tonic-gatepackage.
239*0Sstevel@tonic-gate
240*0Sstevel@tonic-gateBecause of this mechanism it is important that B<AutoLoader> is always
241*0Sstevel@tonic-gateC<use>d and not C<require>d.
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gate=head2 Using B<AutoLoader>'s AUTOLOAD Subroutine
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gateIn order to use B<AutoLoader>'s AUTOLOAD subroutine you I<must>
246*0Sstevel@tonic-gateexplicitly import it:
247*0Sstevel@tonic-gate
248*0Sstevel@tonic-gate    use AutoLoader 'AUTOLOAD';
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate=head2 Overriding B<AutoLoader>'s AUTOLOAD Subroutine
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gateSome modules, mainly extensions, provide their own AUTOLOAD subroutines.
253*0Sstevel@tonic-gateThey typically need to check for some special cases (such as constants)
254*0Sstevel@tonic-gateand then fallback to B<AutoLoader>'s AUTOLOAD for the rest.
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gateSuch modules should I<not> import B<AutoLoader>'s AUTOLOAD subroutine.
257*0Sstevel@tonic-gateInstead, they should define their own AUTOLOAD subroutines along these
258*0Sstevel@tonic-gatelines:
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate    use AutoLoader;
261*0Sstevel@tonic-gate    use Carp;
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate    sub AUTOLOAD {
264*0Sstevel@tonic-gate        my $sub = $AUTOLOAD;
265*0Sstevel@tonic-gate        (my $constname = $sub) =~ s/.*:://;
266*0Sstevel@tonic-gate        my $val = constant($constname, @_ ? $_[0] : 0);
267*0Sstevel@tonic-gate        if ($! != 0) {
268*0Sstevel@tonic-gate            if ($! =~ /Invalid/ || $!{EINVAL}) {
269*0Sstevel@tonic-gate                $AutoLoader::AUTOLOAD = $sub;
270*0Sstevel@tonic-gate                goto &AutoLoader::AUTOLOAD;
271*0Sstevel@tonic-gate            }
272*0Sstevel@tonic-gate            else {
273*0Sstevel@tonic-gate                croak "Your vendor has not defined constant $constname";
274*0Sstevel@tonic-gate            }
275*0Sstevel@tonic-gate        }
276*0Sstevel@tonic-gate        *$sub = sub { $val }; # same as: eval "sub $sub { $val }";
277*0Sstevel@tonic-gate        goto &$sub;
278*0Sstevel@tonic-gate    }
279*0Sstevel@tonic-gate
280*0Sstevel@tonic-gateIf any module's own AUTOLOAD subroutine has no need to fallback to the
281*0Sstevel@tonic-gateAutoLoader's AUTOLOAD subroutine (because it doesn't have any AutoSplit
282*0Sstevel@tonic-gatesubroutines), then that module should not use B<AutoLoader> at all.
283*0Sstevel@tonic-gate
284*0Sstevel@tonic-gate=head2 Package Lexicals
285*0Sstevel@tonic-gate
286*0Sstevel@tonic-gatePackage lexicals declared with C<my> in the main block of a package
287*0Sstevel@tonic-gateusing B<AutoLoader> will not be visible to auto-loaded subroutines, due to
288*0Sstevel@tonic-gatethe fact that the given scope ends at the C<__END__> marker.  A module
289*0Sstevel@tonic-gateusing such variables as package globals will not work properly under the
290*0Sstevel@tonic-gateB<AutoLoader>.
291*0Sstevel@tonic-gate
292*0Sstevel@tonic-gateThe C<vars> pragma (see L<perlmod/"vars">) may be used in such
293*0Sstevel@tonic-gatesituations as an alternative to explicitly qualifying all globals with
294*0Sstevel@tonic-gatethe package namespace.  Variables pre-declared with this pragma will be
295*0Sstevel@tonic-gatevisible to any autoloaded routines (but will not be invisible outside
296*0Sstevel@tonic-gatethe package, unfortunately).
297*0Sstevel@tonic-gate
298*0Sstevel@tonic-gate=head2 Not Using AutoLoader
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gateYou can stop using AutoLoader by simply
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate	no AutoLoader;
303*0Sstevel@tonic-gate
304*0Sstevel@tonic-gate=head2 B<AutoLoader> vs. B<SelfLoader>
305*0Sstevel@tonic-gate
306*0Sstevel@tonic-gateThe B<AutoLoader> is similar in purpose to B<SelfLoader>: both delay the
307*0Sstevel@tonic-gateloading of subroutines.
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gateB<SelfLoader> uses the C<__DATA__> marker rather than C<__END__>.
310*0Sstevel@tonic-gateWhile this avoids the use of a hierarchy of disk files and the
311*0Sstevel@tonic-gateassociated open/close for each routine loaded, B<SelfLoader> suffers a
312*0Sstevel@tonic-gatestartup speed disadvantage in the one-time parsing of the lines after
313*0Sstevel@tonic-gateC<__DATA__>, after which routines are cached.  B<SelfLoader> can also
314*0Sstevel@tonic-gatehandle multiple packages in a file.
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gateB<AutoLoader> only reads code as it is requested, and in many cases
317*0Sstevel@tonic-gateshould be faster, but requires a mechanism like B<AutoSplit> be used to
318*0Sstevel@tonic-gatecreate the individual files.  L<ExtUtils::MakeMaker> will invoke
319*0Sstevel@tonic-gateB<AutoSplit> automatically if B<AutoLoader> is used in a module source
320*0Sstevel@tonic-gatefile.
321*0Sstevel@tonic-gate
322*0Sstevel@tonic-gate=head1 CAVEATS
323*0Sstevel@tonic-gate
324*0Sstevel@tonic-gateAutoLoaders prior to Perl 5.002 had a slightly different interface.  Any
325*0Sstevel@tonic-gateold modules which use B<AutoLoader> should be changed to the new calling
326*0Sstevel@tonic-gatestyle.  Typically this just means changing a require to a use, adding
327*0Sstevel@tonic-gatethe explicit C<'AUTOLOAD'> import if needed, and removing B<AutoLoader>
328*0Sstevel@tonic-gatefrom C<@ISA>.
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gateOn systems with restrictions on file name length, the file corresponding
331*0Sstevel@tonic-gateto a subroutine may have a shorter name that the routine itself.  This
332*0Sstevel@tonic-gatecan lead to conflicting file names.  The I<AutoSplit> package warns of
333*0Sstevel@tonic-gatethese potential conflicts when used to split a module.
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gateAutoLoader may fail to find the autosplit files (or even find the wrong
336*0Sstevel@tonic-gateones) in cases where C<@INC> contains relative paths, B<and> the program
337*0Sstevel@tonic-gatedoes C<chdir>.
338*0Sstevel@tonic-gate
339*0Sstevel@tonic-gate=head1 SEE ALSO
340*0Sstevel@tonic-gate
341*0Sstevel@tonic-gateL<SelfLoader> - an autoloader that doesn't use external files.
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gate=cut
344