xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/autouse.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gatepackage autouse;
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gate#use strict;		# debugging only
4*0Sstevel@tonic-gateuse 5.003_90;		# ->can, for my $var
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gate$autouse::VERSION = '1.03';
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gate$autouse::DEBUG ||= 0;
9*0Sstevel@tonic-gate
10*0Sstevel@tonic-gatesub vet_import ($);
11*0Sstevel@tonic-gate
12*0Sstevel@tonic-gatesub croak {
13*0Sstevel@tonic-gate    require Carp;
14*0Sstevel@tonic-gate    Carp::croak(@_);
15*0Sstevel@tonic-gate}
16*0Sstevel@tonic-gate
17*0Sstevel@tonic-gatesub import {
18*0Sstevel@tonic-gate    my $class = @_ ? shift : 'autouse';
19*0Sstevel@tonic-gate    croak "usage: use $class MODULE [,SUBS...]" unless @_;
20*0Sstevel@tonic-gate    my $module = shift;
21*0Sstevel@tonic-gate
22*0Sstevel@tonic-gate    (my $pm = $module) =~ s{::}{/}g;
23*0Sstevel@tonic-gate    $pm .= '.pm';
24*0Sstevel@tonic-gate    if (exists $INC{$pm}) {
25*0Sstevel@tonic-gate	vet_import $module;
26*0Sstevel@tonic-gate	local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
27*0Sstevel@tonic-gate	# $Exporter::Verbose = 1;
28*0Sstevel@tonic-gate	return $module->import(map { (my $f = $_) =~ s/\(.*?\)$//; $f } @_);
29*0Sstevel@tonic-gate    }
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate    # It is not loaded: need to do real work.
32*0Sstevel@tonic-gate    my $callpkg = caller(0);
33*0Sstevel@tonic-gate    print "autouse called from $callpkg\n" if $autouse::DEBUG;
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gate    my $index;
36*0Sstevel@tonic-gate    for my $f (@_) {
37*0Sstevel@tonic-gate	my $proto;
38*0Sstevel@tonic-gate	$proto = $1 if (my $func = $f) =~ s/\((.*)\)$//;
39*0Sstevel@tonic-gate
40*0Sstevel@tonic-gate	my $closure_import_func = $func;	# Full name
41*0Sstevel@tonic-gate	my $closure_func = $func;		# Name inside package
42*0Sstevel@tonic-gate	my $index = rindex($func, '::');
43*0Sstevel@tonic-gate	if ($index == -1) {
44*0Sstevel@tonic-gate	    $closure_import_func = "${callpkg}::$func";
45*0Sstevel@tonic-gate	} else {
46*0Sstevel@tonic-gate	    $closure_func = substr $func, $index + 2;
47*0Sstevel@tonic-gate	    croak "autouse into different package attempted"
48*0Sstevel@tonic-gate		unless substr($func, 0, $index) eq $module;
49*0Sstevel@tonic-gate	}
50*0Sstevel@tonic-gate
51*0Sstevel@tonic-gate	my $load_sub = sub {
52*0Sstevel@tonic-gate	    unless ($INC{$pm}) {
53*0Sstevel@tonic-gate		eval {require $pm};
54*0Sstevel@tonic-gate		die if $@;
55*0Sstevel@tonic-gate		vet_import $module;
56*0Sstevel@tonic-gate	    }
57*0Sstevel@tonic-gate            no warnings 'redefine';
58*0Sstevel@tonic-gate	    *$closure_import_func = \&{"${module}::$closure_func"};
59*0Sstevel@tonic-gate	    print "autousing $module; "
60*0Sstevel@tonic-gate		  ."imported $closure_func as $closure_import_func\n"
61*0Sstevel@tonic-gate		if $autouse::DEBUG;
62*0Sstevel@tonic-gate	    goto &$closure_import_func;
63*0Sstevel@tonic-gate	};
64*0Sstevel@tonic-gate
65*0Sstevel@tonic-gate	if (defined $proto) {
66*0Sstevel@tonic-gate	    *$closure_import_func = eval "sub ($proto) { &\$load_sub }";
67*0Sstevel@tonic-gate	} else {
68*0Sstevel@tonic-gate	    *$closure_import_func = $load_sub;
69*0Sstevel@tonic-gate	}
70*0Sstevel@tonic-gate    }
71*0Sstevel@tonic-gate}
72*0Sstevel@tonic-gate
73*0Sstevel@tonic-gatesub vet_import ($) {
74*0Sstevel@tonic-gate    my $module = shift;
75*0Sstevel@tonic-gate    if (my $import = $module->can('import')) {
76*0Sstevel@tonic-gate	croak "autoused module has unique import() method"
77*0Sstevel@tonic-gate	    unless defined(&Exporter::import)
78*0Sstevel@tonic-gate		   && $import == \&Exporter::import;
79*0Sstevel@tonic-gate    }
80*0Sstevel@tonic-gate}
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate1;
83*0Sstevel@tonic-gate
84*0Sstevel@tonic-gate__END__
85*0Sstevel@tonic-gate
86*0Sstevel@tonic-gate=head1 NAME
87*0Sstevel@tonic-gate
88*0Sstevel@tonic-gateautouse - postpone load of modules until a function is used
89*0Sstevel@tonic-gate
90*0Sstevel@tonic-gate=head1 SYNOPSIS
91*0Sstevel@tonic-gate
92*0Sstevel@tonic-gate  use autouse 'Carp' => qw(carp croak);
93*0Sstevel@tonic-gate  carp "this carp was predeclared and autoused ";
94*0Sstevel@tonic-gate
95*0Sstevel@tonic-gate=head1 DESCRIPTION
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gateIf the module C<Module> is already loaded, then the declaration
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate  use autouse 'Module' => qw(func1 func2($;$));
100*0Sstevel@tonic-gate
101*0Sstevel@tonic-gateis equivalent to
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate  use Module qw(func1 func2);
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gateif C<Module> defines func2() with prototype C<($;$)>, and func1() has
106*0Sstevel@tonic-gateno prototypes.  (At least if C<Module> uses C<Exporter>'s C<import>,
107*0Sstevel@tonic-gateotherwise it is a fatal error.)
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gateIf the module C<Module> is not loaded yet, then the above declaration
110*0Sstevel@tonic-gatedeclares functions func1() and func2() in the current package.  When
111*0Sstevel@tonic-gatethese functions are called, they load the package C<Module> if needed,
112*0Sstevel@tonic-gateand substitute themselves with the correct definitions.
113*0Sstevel@tonic-gate
114*0Sstevel@tonic-gate=begin _deprecated
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gate   use Module qw(Module::func3);
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gatewill work and is the equivalent to:
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate   use Module qw(func3);
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gateIt is not a very useful feature and has been deprecated.
123*0Sstevel@tonic-gate
124*0Sstevel@tonic-gate=end _deprecated
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gate=head1 WARNING
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gateUsing C<autouse> will move important steps of your program's execution
130*0Sstevel@tonic-gatefrom compile time to runtime.  This can
131*0Sstevel@tonic-gate
132*0Sstevel@tonic-gate=over 4
133*0Sstevel@tonic-gate
134*0Sstevel@tonic-gate=item *
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gateBreak the execution of your program if the module you C<autouse>d has
137*0Sstevel@tonic-gatesome initialization which it expects to be done early.
138*0Sstevel@tonic-gate
139*0Sstevel@tonic-gate=item *
140*0Sstevel@tonic-gate
141*0Sstevel@tonic-gatehide bugs in your code since important checks (like correctness of
142*0Sstevel@tonic-gateprototypes) is moved from compile time to runtime.  In particular, if
143*0Sstevel@tonic-gatethe prototype you specified on C<autouse> line is wrong, you will not
144*0Sstevel@tonic-gatefind it out until the corresponding function is executed.  This will be
145*0Sstevel@tonic-gatevery unfortunate for functions which are not always called (note that
146*0Sstevel@tonic-gatefor such functions C<autouse>ing gives biggest win, for a workaround
147*0Sstevel@tonic-gatesee below).
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate=back
150*0Sstevel@tonic-gate
151*0Sstevel@tonic-gateTo alleviate the second problem (partially) it is advised to write
152*0Sstevel@tonic-gateyour scripts like this:
153*0Sstevel@tonic-gate
154*0Sstevel@tonic-gate  use Module;
155*0Sstevel@tonic-gate  use autouse Module => qw(carp($) croak(&$));
156*0Sstevel@tonic-gate  carp "this carp was predeclared and autoused ";
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gateThe first line ensures that the errors in your argument specification
159*0Sstevel@tonic-gateare found early.  When you ship your application you should comment
160*0Sstevel@tonic-gateout the first line, since it makes the second one useless.
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gate=head1 AUTHOR
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gateIlya Zakharevich (ilya@math.ohio-state.edu)
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gate=head1 SEE ALSO
167*0Sstevel@tonic-gate
168*0Sstevel@tonic-gateperl(1).
169*0Sstevel@tonic-gate
170*0Sstevel@tonic-gate=cut
171