xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/attributes.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gatepackage attributes;
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gateour $VERSION = 0.06;
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gate@EXPORT_OK = qw(get reftype);
6*0Sstevel@tonic-gate@EXPORT = ();
7*0Sstevel@tonic-gate%EXPORT_TAGS = (ALL => [@EXPORT, @EXPORT_OK]);
8*0Sstevel@tonic-gate
9*0Sstevel@tonic-gateuse strict;
10*0Sstevel@tonic-gate
11*0Sstevel@tonic-gatesub croak {
12*0Sstevel@tonic-gate    require Carp;
13*0Sstevel@tonic-gate    goto &Carp::croak;
14*0Sstevel@tonic-gate}
15*0Sstevel@tonic-gate
16*0Sstevel@tonic-gatesub carp {
17*0Sstevel@tonic-gate    require Carp;
18*0Sstevel@tonic-gate    goto &Carp::carp;
19*0Sstevel@tonic-gate}
20*0Sstevel@tonic-gate
21*0Sstevel@tonic-gate## forward declaration(s) rather than wrapping the bootstrap call in BEGIN{}
22*0Sstevel@tonic-gate#sub reftype ($) ;
23*0Sstevel@tonic-gate#sub _fetch_attrs ($) ;
24*0Sstevel@tonic-gate#sub _guess_stash ($) ;
25*0Sstevel@tonic-gate#sub _modify_attrs ;
26*0Sstevel@tonic-gate#sub _warn_reserved () ;
27*0Sstevel@tonic-gate#
28*0Sstevel@tonic-gate# The extra trips through newATTRSUB in the interpreter wipe out any savings
29*0Sstevel@tonic-gate# from avoiding the BEGIN block.  Just do the bootstrap now.
30*0Sstevel@tonic-gateBEGIN { bootstrap attributes }
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gatesub import {
33*0Sstevel@tonic-gate    @_ > 2 && ref $_[2] or do {
34*0Sstevel@tonic-gate	require Exporter;
35*0Sstevel@tonic-gate	goto &Exporter::import;
36*0Sstevel@tonic-gate    };
37*0Sstevel@tonic-gate    my (undef,$home_stash,$svref,@attrs) = @_;
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate    my $svtype = uc reftype($svref);
40*0Sstevel@tonic-gate    my $pkgmeth;
41*0Sstevel@tonic-gate    $pkgmeth = UNIVERSAL::can($home_stash, "MODIFY_${svtype}_ATTRIBUTES")
42*0Sstevel@tonic-gate	if defined $home_stash && $home_stash ne '';
43*0Sstevel@tonic-gate    my @badattrs;
44*0Sstevel@tonic-gate    if ($pkgmeth) {
45*0Sstevel@tonic-gate	my @pkgattrs = _modify_attrs($svref, @attrs);
46*0Sstevel@tonic-gate	@badattrs = $pkgmeth->($home_stash, $svref, @attrs);
47*0Sstevel@tonic-gate	if (!@badattrs && @pkgattrs) {
48*0Sstevel@tonic-gate	    return unless _warn_reserved;
49*0Sstevel@tonic-gate	    @pkgattrs = grep { m/\A[[:lower:]]+(?:\z|\()/ } @pkgattrs;
50*0Sstevel@tonic-gate	    if (@pkgattrs) {
51*0Sstevel@tonic-gate		for my $attr (@pkgattrs) {
52*0Sstevel@tonic-gate		    $attr =~ s/\(.+\z//s;
53*0Sstevel@tonic-gate		}
54*0Sstevel@tonic-gate		my $s = ((@pkgattrs == 1) ? '' : 's');
55*0Sstevel@tonic-gate		carp "$svtype package attribute$s " .
56*0Sstevel@tonic-gate		    "may clash with future reserved word$s: " .
57*0Sstevel@tonic-gate		    join(' : ' , @pkgattrs);
58*0Sstevel@tonic-gate	    }
59*0Sstevel@tonic-gate	}
60*0Sstevel@tonic-gate    }
61*0Sstevel@tonic-gate    else {
62*0Sstevel@tonic-gate	@badattrs = _modify_attrs($svref, @attrs);
63*0Sstevel@tonic-gate    }
64*0Sstevel@tonic-gate    if (@badattrs) {
65*0Sstevel@tonic-gate	croak "Invalid $svtype attribute" .
66*0Sstevel@tonic-gate	    (( @badattrs == 1 ) ? '' : 's') .
67*0Sstevel@tonic-gate	    ": " .
68*0Sstevel@tonic-gate	    join(' : ', @badattrs);
69*0Sstevel@tonic-gate    }
70*0Sstevel@tonic-gate}
71*0Sstevel@tonic-gate
72*0Sstevel@tonic-gatesub get ($) {
73*0Sstevel@tonic-gate    @_ == 1  && ref $_[0] or
74*0Sstevel@tonic-gate	croak 'Usage: '.__PACKAGE__.'::get $ref';
75*0Sstevel@tonic-gate    my $svref = shift;
76*0Sstevel@tonic-gate    my $svtype = uc reftype $svref;
77*0Sstevel@tonic-gate    my $stash = _guess_stash $svref;
78*0Sstevel@tonic-gate    $stash = caller unless defined $stash;
79*0Sstevel@tonic-gate    my $pkgmeth;
80*0Sstevel@tonic-gate    $pkgmeth = UNIVERSAL::can($stash, "FETCH_${svtype}_ATTRIBUTES")
81*0Sstevel@tonic-gate	if defined $stash && $stash ne '';
82*0Sstevel@tonic-gate    return $pkgmeth ?
83*0Sstevel@tonic-gate		(_fetch_attrs($svref), $pkgmeth->($stash, $svref)) :
84*0Sstevel@tonic-gate		(_fetch_attrs($svref))
85*0Sstevel@tonic-gate	;
86*0Sstevel@tonic-gate}
87*0Sstevel@tonic-gate
88*0Sstevel@tonic-gatesub require_version { goto &UNIVERSAL::VERSION }
89*0Sstevel@tonic-gate
90*0Sstevel@tonic-gate1;
91*0Sstevel@tonic-gate__END__
92*0Sstevel@tonic-gate#The POD goes here
93*0Sstevel@tonic-gate
94*0Sstevel@tonic-gate=head1 NAME
95*0Sstevel@tonic-gate
96*0Sstevel@tonic-gateattributes - get/set subroutine or variable attributes
97*0Sstevel@tonic-gate
98*0Sstevel@tonic-gate=head1 SYNOPSIS
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate  sub foo : method ;
101*0Sstevel@tonic-gate  my ($x,@y,%z) : Bent = 1;
102*0Sstevel@tonic-gate  my $s = sub : method { ... };
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gate  use attributes ();	# optional, to get subroutine declarations
105*0Sstevel@tonic-gate  my @attrlist = attributes::get(\&foo);
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate  use attributes 'get'; # import the attributes::get subroutine
108*0Sstevel@tonic-gate  my @attrlist = get \&foo;
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gate=head1 DESCRIPTION
111*0Sstevel@tonic-gate
112*0Sstevel@tonic-gateSubroutine declarations and definitions may optionally have attribute lists
113*0Sstevel@tonic-gateassociated with them.  (Variable C<my> declarations also may, but see the
114*0Sstevel@tonic-gatewarning below.)  Perl handles these declarations by passing some information
115*0Sstevel@tonic-gateabout the call site and the thing being declared along with the attribute
116*0Sstevel@tonic-gatelist to this module.  In particular, the first example above is equivalent to
117*0Sstevel@tonic-gatethe following:
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate    use attributes __PACKAGE__, \&foo, 'method';
120*0Sstevel@tonic-gate
121*0Sstevel@tonic-gateThe second example in the synopsis does something equivalent to this:
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate    use attributes ();
124*0Sstevel@tonic-gate    my ($x,@y,%z);
125*0Sstevel@tonic-gate    attributes::->import(__PACKAGE__, \$x, 'Bent');
126*0Sstevel@tonic-gate    attributes::->import(__PACKAGE__, \@y, 'Bent');
127*0Sstevel@tonic-gate    attributes::->import(__PACKAGE__, \%z, 'Bent');
128*0Sstevel@tonic-gate    ($x,@y,%z) = 1;
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gateYes, that's a lot of expansion.
131*0Sstevel@tonic-gate
132*0Sstevel@tonic-gateB<WARNING>: attribute declarations for variables are still evolving.
133*0Sstevel@tonic-gateThe semantics and interfaces of such declarations could change in
134*0Sstevel@tonic-gatefuture versions.  They are present for purposes of experimentation
135*0Sstevel@tonic-gatewith what the semantics ought to be.  Do not rely on the current
136*0Sstevel@tonic-gateimplementation of this feature.
137*0Sstevel@tonic-gate
138*0Sstevel@tonic-gateThere are only a few attributes currently handled by Perl itself (or
139*0Sstevel@tonic-gatedirectly by this module, depending on how you look at it.)  However,
140*0Sstevel@tonic-gatepackage-specific attributes are allowed by an extension mechanism.
141*0Sstevel@tonic-gate(See L<"Package-specific Attribute Handling"> below.)
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gateThe setting of subroutine attributes happens at compile time.
144*0Sstevel@tonic-gateVariable attributes in C<our> declarations are also applied at compile time.
145*0Sstevel@tonic-gateHowever, C<my> variables get their attributes applied at run-time.
146*0Sstevel@tonic-gateThis means that you have to I<reach> the run-time component of the C<my>
147*0Sstevel@tonic-gatebefore those attributes will get applied.  For example:
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate    my $x : Bent = 42 if 0;
150*0Sstevel@tonic-gate
151*0Sstevel@tonic-gatewill neither assign 42 to $x I<nor> will it apply the C<Bent> attribute
152*0Sstevel@tonic-gateto the variable.
153*0Sstevel@tonic-gate
154*0Sstevel@tonic-gateAn attempt to set an unrecognized attribute is a fatal error.  (The
155*0Sstevel@tonic-gateerror is trappable, but it still stops the compilation within that
156*0Sstevel@tonic-gateC<eval>.)  Setting an attribute with a name that's all lowercase
157*0Sstevel@tonic-gateletters that's not a built-in attribute (such as "foo") will result in
158*0Sstevel@tonic-gatea warning with B<-w> or C<use warnings 'reserved'>.
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate=head2 Built-in Attributes
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gateThe following are the built-in attributes for subroutines:
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gate=over 4
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gate=item locked
167*0Sstevel@tonic-gate
168*0Sstevel@tonic-gateB<5.005 threads only!  The use of the "locked" attribute currently
169*0Sstevel@tonic-gateonly makes sense if you are using the deprecated "Perl 5.005 threads"
170*0Sstevel@tonic-gateimplementation of threads.>
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gateSetting this attribute is only meaningful when the subroutine or
173*0Sstevel@tonic-gatemethod is to be called by multiple threads.  When set on a method
174*0Sstevel@tonic-gatesubroutine (i.e., one marked with the B<method> attribute below),
175*0Sstevel@tonic-gatePerl ensures that any invocation of it implicitly locks its first
176*0Sstevel@tonic-gateargument before execution.  When set on a non-method subroutine,
177*0Sstevel@tonic-gatePerl ensures that a lock is taken on the subroutine itself before
178*0Sstevel@tonic-gateexecution.  The semantics of the lock are exactly those of one
179*0Sstevel@tonic-gateexplicitly taken with the C<lock> operator immediately after the
180*0Sstevel@tonic-gatesubroutine is entered.
181*0Sstevel@tonic-gate
182*0Sstevel@tonic-gate=item method
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gateIndicates that the referenced subroutine is a method.
185*0Sstevel@tonic-gateThis has a meaning when taken together with the B<locked> attribute,
186*0Sstevel@tonic-gateas described there.  It also means that a subroutine so marked
187*0Sstevel@tonic-gatewill not trigger the "Ambiguous call resolved as CORE::%s" warning.
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate=item lvalue
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gateIndicates that the referenced subroutine is a valid lvalue and can
192*0Sstevel@tonic-gatebe assigned to. The subroutine must return a modifiable value such
193*0Sstevel@tonic-gateas a scalar variable, as described in L<perlsub>.
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate=back
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gateFor global variables there is C<unique> attribute: see L<perlfunc/our>.
198*0Sstevel@tonic-gate
199*0Sstevel@tonic-gate=head2 Available Subroutines
200*0Sstevel@tonic-gate
201*0Sstevel@tonic-gateThe following subroutines are available for general use once this module
202*0Sstevel@tonic-gatehas been loaded:
203*0Sstevel@tonic-gate
204*0Sstevel@tonic-gate=over 4
205*0Sstevel@tonic-gate
206*0Sstevel@tonic-gate=item get
207*0Sstevel@tonic-gate
208*0Sstevel@tonic-gateThis routine expects a single parameter--a reference to a
209*0Sstevel@tonic-gatesubroutine or variable.  It returns a list of attributes, which may be
210*0Sstevel@tonic-gateempty.  If passed invalid arguments, it uses die() (via L<Carp::croak|Carp>)
211*0Sstevel@tonic-gateto raise a fatal exception.  If it can find an appropriate package name
212*0Sstevel@tonic-gatefor a class method lookup, it will include the results from a
213*0Sstevel@tonic-gateC<FETCH_I<type>_ATTRIBUTES> call in its return list, as described in
214*0Sstevel@tonic-gateL<"Package-specific Attribute Handling"> below.
215*0Sstevel@tonic-gateOtherwise, only L<built-in attributes|"Built-in Attributes"> will be returned.
216*0Sstevel@tonic-gate
217*0Sstevel@tonic-gate=item reftype
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gateThis routine expects a single parameter--a reference to a subroutine or
220*0Sstevel@tonic-gatevariable.  It returns the built-in type of the referenced variable,
221*0Sstevel@tonic-gateignoring any package into which it might have been blessed.
222*0Sstevel@tonic-gateThis can be useful for determining the I<type> value which forms part of
223*0Sstevel@tonic-gatethe method names described in L<"Package-specific Attribute Handling"> below.
224*0Sstevel@tonic-gate
225*0Sstevel@tonic-gate=back
226*0Sstevel@tonic-gate
227*0Sstevel@tonic-gateNote that these routines are I<not> exported by default.
228*0Sstevel@tonic-gate
229*0Sstevel@tonic-gate=head2 Package-specific Attribute Handling
230*0Sstevel@tonic-gate
231*0Sstevel@tonic-gateB<WARNING>: the mechanisms described here are still experimental.  Do not
232*0Sstevel@tonic-gaterely on the current implementation.  In particular, there is no provision
233*0Sstevel@tonic-gatefor applying package attributes to 'cloned' copies of subroutines used as
234*0Sstevel@tonic-gateclosures.  (See L<perlref/"Making References"> for information on closures.)
235*0Sstevel@tonic-gatePackage-specific attribute handling may change incompatibly in a future
236*0Sstevel@tonic-gaterelease.
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gateWhen an attribute list is present in a declaration, a check is made to see
239*0Sstevel@tonic-gatewhether an attribute 'modify' handler is present in the appropriate package
240*0Sstevel@tonic-gate(or its @ISA inheritance tree).  Similarly, when C<attributes::get> is
241*0Sstevel@tonic-gatecalled on a valid reference, a check is made for an appropriate attribute
242*0Sstevel@tonic-gate'fetch' handler.  See L<"EXAMPLES"> to see how the "appropriate package"
243*0Sstevel@tonic-gatedetermination works.
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gateThe handler names are based on the underlying type of the variable being
246*0Sstevel@tonic-gatedeclared or of the reference passed.  Because these attributes are
247*0Sstevel@tonic-gateassociated with subroutine or variable declarations, this deliberately
248*0Sstevel@tonic-gateignores any possibility of being blessed into some package.  Thus, a
249*0Sstevel@tonic-gatesubroutine declaration uses "CODE" as its I<type>, and even a blessed
250*0Sstevel@tonic-gatehash reference uses "HASH" as its I<type>.
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gateThe class methods invoked for modifying and fetching are these:
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate=over 4
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gate=item FETCH_I<type>_ATTRIBUTES
257*0Sstevel@tonic-gate
258*0Sstevel@tonic-gateThis method receives a single argument, which is a reference to the
259*0Sstevel@tonic-gatevariable or subroutine for which package-defined attributes are desired.
260*0Sstevel@tonic-gateThe expected return value is a list of associated attributes.
261*0Sstevel@tonic-gateThis list may be empty.
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate=item MODIFY_I<type>_ATTRIBUTES
264*0Sstevel@tonic-gate
265*0Sstevel@tonic-gateThis method is called with two fixed arguments, followed by the list of
266*0Sstevel@tonic-gateattributes from the relevant declaration.  The two fixed arguments are
267*0Sstevel@tonic-gatethe relevant package name and a reference to the declared subroutine or
268*0Sstevel@tonic-gatevariable.  The expected return value is a list of attributes which were
269*0Sstevel@tonic-gatenot recognized by this handler.  Note that this allows for a derived class
270*0Sstevel@tonic-gateto delegate a call to its base class, and then only examine the attributes
271*0Sstevel@tonic-gatewhich the base class didn't already handle for it.
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gateThe call to this method is currently made I<during> the processing of the
274*0Sstevel@tonic-gatedeclaration.  In particular, this means that a subroutine reference will
275*0Sstevel@tonic-gateprobably be for an undefined subroutine, even if this declaration is
276*0Sstevel@tonic-gateactually part of the definition.
277*0Sstevel@tonic-gate
278*0Sstevel@tonic-gate=back
279*0Sstevel@tonic-gate
280*0Sstevel@tonic-gateCalling C<attributes::get()> from within the scope of a null package
281*0Sstevel@tonic-gatedeclaration C<package ;> for an unblessed variable reference will
282*0Sstevel@tonic-gatenot provide any starting package name for the 'fetch' method lookup.
283*0Sstevel@tonic-gateThus, this circumstance will not result in a method call for package-defined
284*0Sstevel@tonic-gateattributes.  A named subroutine knows to which symbol table entry it belongs
285*0Sstevel@tonic-gate(or originally belonged), and it will use the corresponding package.
286*0Sstevel@tonic-gateAn anonymous subroutine knows the package name into which it was compiled
287*0Sstevel@tonic-gate(unless it was also compiled with a null package declaration), and so it
288*0Sstevel@tonic-gatewill use that package name.
289*0Sstevel@tonic-gate
290*0Sstevel@tonic-gate=head2 Syntax of Attribute Lists
291*0Sstevel@tonic-gate
292*0Sstevel@tonic-gateAn attribute list is a sequence of attribute specifications, separated by
293*0Sstevel@tonic-gatewhitespace or a colon (with optional whitespace).
294*0Sstevel@tonic-gateEach attribute specification is a simple
295*0Sstevel@tonic-gatename, optionally followed by a parenthesised parameter list.
296*0Sstevel@tonic-gateIf such a parameter list is present, it is scanned past as for the rules
297*0Sstevel@tonic-gatefor the C<q()> operator.  (See L<perlop/"Quote and Quote-like Operators">.)
298*0Sstevel@tonic-gateThe parameter list is passed as it was found, however, and not as per C<q()>.
299*0Sstevel@tonic-gate
300*0Sstevel@tonic-gateSome examples of syntactically valid attribute lists:
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate    switch(10,foo(7,3))  :  expensive
303*0Sstevel@tonic-gate    Ugly('\(") :Bad
304*0Sstevel@tonic-gate    _5x5
305*0Sstevel@tonic-gate    locked method
306*0Sstevel@tonic-gate
307*0Sstevel@tonic-gateSome examples of syntactically invalid attribute lists (with annotation):
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gate    switch(10,foo()		# ()-string not balanced
310*0Sstevel@tonic-gate    Ugly('(')			# ()-string not balanced
311*0Sstevel@tonic-gate    5x5				# "5x5" not a valid identifier
312*0Sstevel@tonic-gate    Y2::north			# "Y2::north" not a simple identifier
313*0Sstevel@tonic-gate    foo + bar			# "+" neither a colon nor whitespace
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate=head1 EXPORTS
316*0Sstevel@tonic-gate
317*0Sstevel@tonic-gate=head2 Default exports
318*0Sstevel@tonic-gate
319*0Sstevel@tonic-gateNone.
320*0Sstevel@tonic-gate
321*0Sstevel@tonic-gate=head2 Available exports
322*0Sstevel@tonic-gate
323*0Sstevel@tonic-gateThe routines C<get> and C<reftype> are exportable.
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate=head2 Export tags defined
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gateThe C<:ALL> tag will get all of the above exports.
328*0Sstevel@tonic-gate
329*0Sstevel@tonic-gate=head1 EXAMPLES
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gateHere are some samples of syntactically valid declarations, with annotation
332*0Sstevel@tonic-gateas to how they resolve internally into C<use attributes> invocations by
333*0Sstevel@tonic-gateperl.  These examples are primarily useful to see how the "appropriate
334*0Sstevel@tonic-gatepackage" is found for the possible method lookups for package-defined
335*0Sstevel@tonic-gateattributes.
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gate=over 4
338*0Sstevel@tonic-gate
339*0Sstevel@tonic-gate=item 1.
340*0Sstevel@tonic-gate
341*0Sstevel@tonic-gateCode:
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gate    package Canine;
344*0Sstevel@tonic-gate    package Dog;
345*0Sstevel@tonic-gate    my Canine $spot : Watchful ;
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gateEffect:
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate    use attributes ();
350*0Sstevel@tonic-gate    attributes::->import(Canine => \$spot, "Watchful");
351*0Sstevel@tonic-gate
352*0Sstevel@tonic-gate=item 2.
353*0Sstevel@tonic-gate
354*0Sstevel@tonic-gateCode:
355*0Sstevel@tonic-gate
356*0Sstevel@tonic-gate    package Felis;
357*0Sstevel@tonic-gate    my $cat : Nervous;
358*0Sstevel@tonic-gate
359*0Sstevel@tonic-gateEffect:
360*0Sstevel@tonic-gate
361*0Sstevel@tonic-gate    use attributes ();
362*0Sstevel@tonic-gate    attributes::->import(Felis => \$cat, "Nervous");
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate=item 3.
365*0Sstevel@tonic-gate
366*0Sstevel@tonic-gateCode:
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gate    package X;
369*0Sstevel@tonic-gate    sub foo : locked ;
370*0Sstevel@tonic-gate
371*0Sstevel@tonic-gateEffect:
372*0Sstevel@tonic-gate
373*0Sstevel@tonic-gate    use attributes X => \&foo, "locked";
374*0Sstevel@tonic-gate
375*0Sstevel@tonic-gate=item 4.
376*0Sstevel@tonic-gate
377*0Sstevel@tonic-gateCode:
378*0Sstevel@tonic-gate
379*0Sstevel@tonic-gate    package X;
380*0Sstevel@tonic-gate    sub Y::x : locked { 1 }
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gateEffect:
383*0Sstevel@tonic-gate
384*0Sstevel@tonic-gate    use attributes Y => \&Y::x, "locked";
385*0Sstevel@tonic-gate
386*0Sstevel@tonic-gate=item 5.
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gateCode:
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gate    package X;
391*0Sstevel@tonic-gate    sub foo { 1 }
392*0Sstevel@tonic-gate
393*0Sstevel@tonic-gate    package Y;
394*0Sstevel@tonic-gate    BEGIN { *bar = \&X::foo; }
395*0Sstevel@tonic-gate
396*0Sstevel@tonic-gate    package Z;
397*0Sstevel@tonic-gate    sub Y::bar : locked ;
398*0Sstevel@tonic-gate
399*0Sstevel@tonic-gateEffect:
400*0Sstevel@tonic-gate
401*0Sstevel@tonic-gate    use attributes X => \&X::foo, "locked";
402*0Sstevel@tonic-gate
403*0Sstevel@tonic-gate=back
404*0Sstevel@tonic-gate
405*0Sstevel@tonic-gateThis last example is purely for purposes of completeness.  You should not
406*0Sstevel@tonic-gatebe trying to mess with the attributes of something in a package that's
407*0Sstevel@tonic-gatenot your own.
408*0Sstevel@tonic-gate
409*0Sstevel@tonic-gate=head1 SEE ALSO
410*0Sstevel@tonic-gate
411*0Sstevel@tonic-gateL<perlsub/"Private Variables via my()"> and
412*0Sstevel@tonic-gateL<perlsub/"Subroutine Attributes"> for details on the basic declarations;
413*0Sstevel@tonic-gateL<attrs> for the obsolescent form of subroutine attribute specification
414*0Sstevel@tonic-gatewhich this module replaces;
415*0Sstevel@tonic-gateL<perlfunc/use> for details on the normal invocation mechanism.
416*0Sstevel@tonic-gate
417*0Sstevel@tonic-gate=cut
418*0Sstevel@tonic-gate
419