line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::MethodVars; |
2
|
1
|
|
|
1
|
|
1145
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
52
|
|
3
|
1
|
|
|
1
|
|
8
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
43
|
|
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
14204
|
use NEXT; |
|
1
|
|
|
|
|
3785
|
|
|
1
|
|
|
|
|
1895
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '1.'.qw $Rev: 133 $[1]; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our %Configs; # Needs to be accessible to Class::Framework |
10
|
|
|
|
|
|
|
my %OptionsMap = ( |
11
|
|
|
|
|
|
|
'^args'=>'hatargs', |
12
|
|
|
|
|
|
|
'hatargs'=>'hatargs', |
13
|
|
|
|
|
|
|
'varargs'=>'varargs', |
14
|
|
|
|
|
|
|
'^fields'=>'hatfields', |
15
|
|
|
|
|
|
|
'hatfields'=>'hatfields', |
16
|
|
|
|
|
|
|
'varfields'=>'varfields', |
17
|
|
|
|
|
|
|
'^this'=>'hatthis', |
18
|
|
|
|
|
|
|
'hatthis'=>'hatthis', |
19
|
|
|
|
|
|
|
'varthis'=>'varthis', |
20
|
|
|
|
|
|
|
'subthis'=>'subthis', |
21
|
|
|
|
|
|
|
'^class'=>'hatclass', |
22
|
|
|
|
|
|
|
'hatclass'=>'hatclass', |
23
|
|
|
|
|
|
|
'varclass'=>'varclass', |
24
|
|
|
|
|
|
|
'subclass'=>'subclass', |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
'debug'=>'debug', |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
my %DefaultOptions = ( |
29
|
|
|
|
|
|
|
hatargs=>1, |
30
|
|
|
|
|
|
|
hatfields=>1, |
31
|
|
|
|
|
|
|
subthis=>1, |
32
|
|
|
|
|
|
|
subclass=>1, |
33
|
|
|
|
|
|
|
# No varthis and varclass because that causes an implicit use vars which is bad for a default. |
34
|
|
|
|
|
|
|
); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub __DefaultConfigs() { |
37
|
|
|
|
|
|
|
return { |
38
|
1
|
|
|
1
|
|
16
|
fieldhatprefix=>"", |
39
|
|
|
|
|
|
|
fieldvarprefix=>"", |
40
|
|
|
|
|
|
|
class=>"__CLASS__", |
41
|
|
|
|
|
|
|
this=>"this", |
42
|
|
|
|
|
|
|
fields=>[], |
43
|
|
|
|
|
|
|
rwfields=>[], |
44
|
|
|
|
|
|
|
rofields=>[], |
45
|
|
|
|
|
|
|
wofields=>[], |
46
|
|
|
|
|
|
|
hiddenfields=>[], |
47
|
|
|
|
|
|
|
options=>{ %DefaultOptions } |
48
|
|
|
|
|
|
|
}; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub import { |
52
|
1
|
|
|
1
|
|
1
|
shift; # You should NEVER be @ISA = "Class::MethodVars" |
53
|
1
|
|
|
|
|
3
|
my $package = caller; |
54
|
1
|
50
|
|
|
|
6
|
if ($Configs{$package}) { |
55
|
0
|
|
|
|
|
0
|
require Carp; |
56
|
0
|
|
|
|
|
0
|
Carp::croak "Double import into this package!"; |
57
|
|
|
|
|
|
|
} |
58
|
1
|
|
33
|
|
|
7
|
my $Config = $Configs{$package}||=__DefaultConfigs; |
59
|
1
|
|
|
|
|
3
|
my $cpos = 0; |
60
|
1
|
|
|
|
|
6
|
while (@_) { |
61
|
0
|
|
|
|
|
0
|
my $cmd = shift; |
62
|
0
|
|
|
|
|
0
|
$cpos++; |
63
|
0
|
0
|
0
|
|
|
0
|
if ($cpos == 1 and ref($cmd)) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
64
|
0
|
|
|
|
|
0
|
push(@{$Config->{rwfields}},@$cmd); |
|
0
|
|
|
|
|
0
|
|
65
|
|
|
|
|
|
|
} elsif ($cmd eq '-this') { |
66
|
0
|
|
|
|
|
0
|
$Config->{this} = shift; |
67
|
|
|
|
|
|
|
} elsif ($cmd eq '-class') { |
68
|
0
|
|
|
|
|
0
|
$Config->{class} = shift; |
69
|
|
|
|
|
|
|
} elsif ($cpos == 1 and not $cmd=~/^[\+-]/) { |
70
|
0
|
|
|
|
|
0
|
push(@{$Config->{rwfields}},$cmd); |
|
0
|
|
|
|
|
0
|
|
71
|
0
|
|
0
|
|
|
0
|
while (@_ and not $_[0]=~/^-/) { |
72
|
0
|
|
|
|
|
0
|
push(@{$Config->{rwfields}},shift); |
|
0
|
|
|
|
|
0
|
|
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
} elsif ($cmd eq '-fields' or $cmd eq '-field') { |
75
|
0
|
0
|
0
|
|
|
0
|
if (@_ and ref($_[0])) { |
76
|
0
|
|
|
|
|
0
|
push(@{$Config->{rwfields}},@{shift()}); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
77
|
|
|
|
|
|
|
} else { |
78
|
0
|
|
0
|
|
|
0
|
while (@_ and not $_[0]=~/^-/) { |
79
|
0
|
|
|
|
|
0
|
push(@{$Config->{rwfields}},shift); |
|
0
|
|
|
|
|
0
|
|
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
} elsif ($cmd =~ /^-(r[wo]|wo|hidden)fields?$/) { |
83
|
0
|
|
|
|
|
0
|
my $fieldtype = lc $1."fields"; |
84
|
0
|
0
|
0
|
|
|
0
|
if (@_ and ref($_[0])) { |
85
|
0
|
|
|
|
|
0
|
push(@{$Config->{$fieldtype}},@{shift()}); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
86
|
|
|
|
|
|
|
} else { |
87
|
0
|
|
0
|
|
|
0
|
while (@_ and not $_[0]=~/^-/) { |
88
|
0
|
|
|
|
|
0
|
push(@{$Config->{$fieldtype}},shift); |
|
0
|
|
|
|
|
0
|
|
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} elsif ($cmd eq '-fieldvarprefix') { |
92
|
0
|
|
|
|
|
0
|
$Config->{fieldvarprefix} = shift; |
93
|
|
|
|
|
|
|
} elsif ($cmd eq '-fieldhatprefix') { |
94
|
0
|
|
|
|
|
0
|
$Config->{fieldhatprefix} = shift; |
95
|
|
|
|
|
|
|
} elsif ($cmd=~/^([+-])(.*)$/ and $OptionsMap{$2}) { |
96
|
0
|
|
|
|
|
0
|
my ($toggle,$option) = ($1,$2); |
97
|
0
|
0
|
0
|
|
|
0
|
if ($toggle eq '-' and @_ and $_[0]=~/^(?:[10]|ON|OFF|TRUE|FALSE)$/i) { # 'it's okay - you would have -fields if expecting field names... |
|
|
|
0
|
|
|
|
|
98
|
0
|
|
|
|
|
0
|
$toggle = shift; |
99
|
|
|
|
|
|
|
} |
100
|
0
|
|
|
|
|
0
|
$toggle = grep { lc($toggle) eq lc($_) } qw( - 1 ON TRUE ); |
|
0
|
|
|
|
|
0
|
|
101
|
0
|
|
|
|
|
0
|
$Config->{options}->{$option} = $toggle; |
102
|
|
|
|
|
|
|
} else { |
103
|
0
|
|
|
|
|
0
|
require Carp; |
104
|
0
|
|
|
|
|
0
|
local $Carp::CarpLevel = 1; |
105
|
0
|
|
|
|
|
0
|
Carp::croak "I don't know what to do with \"$cmd\""; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
1
|
|
|
|
|
2
|
$Config->{fields} = [ Class::MethodVars::_Private::unique(@{$Config->{rwfields}},@{$Config->{rofields}},@{$Config->{wofields}},@{$Config->{hiddenfields}}) ]; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6
|
|
109
|
|
|
|
|
|
|
#FIXME: I should probably whine if people use the same field name for a -rofield as a -wofield (for example). |
110
|
1
|
|
|
|
|
3
|
my @bad_field_names = grep { not /\A\w+\z/ } @{$Config->{fields}}; |
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
4
|
|
111
|
1
|
50
|
|
|
|
4
|
if (@bad_field_names) { |
112
|
0
|
|
|
|
|
0
|
require Carp; |
113
|
0
|
0
|
|
|
|
0
|
if (eval { require Lingua::EN::Inflect; 1 }) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
114
|
0
|
|
|
|
|
0
|
Carp::croak Lingua::EN::Inflect::inflect("Invalid field PL(name,".@bad_field_names."): ").join(", ",@bad_field_names); |
115
|
|
|
|
|
|
|
} else { |
116
|
0
|
|
|
|
|
0
|
local $" = ", "; |
117
|
0
|
|
|
|
|
0
|
Carp::croak "Invalid field name(s): @bad_field_names"; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
} |
120
|
1
|
|
|
|
|
4
|
$Config->{allfields} = [ Class::MethodVars::_Private::findBaseFields($package) ]; # This will pull in self and base fields. |
121
|
1
|
50
|
|
|
|
6
|
$Config->{options}->{subthis} = 0 if $Config->{this}=~/^\$?_$/; |
122
|
1
|
50
|
|
|
|
15
|
$Config->{options}->{subclass} = 0 if $Config->{class}=~/^\$?_$/; |
123
|
1
|
|
|
|
|
67
|
eval 'unshift @'.$package.'::ISA,q('.__PACKAGE__.'::_ATTRS)'; |
124
|
1
|
50
|
|
|
|
41
|
eval 'package '.$package.'; sub '.$Config->{this}.'();' if $Config->{options}->{subthis}; |
125
|
1
|
50
|
|
|
|
37
|
eval 'package '.$package.'; sub '.$Config->{class}.'();' if $Config->{options}->{subclass}; |
126
|
1
|
|
|
|
|
2
|
my @varnames; |
127
|
1
|
50
|
|
|
|
5
|
push(@varnames,$Config->{this}) if $Config->{options}->{varthis}; |
128
|
1
|
50
|
|
|
|
5
|
push(@varnames,$Config->{class}) if $Config->{options}->{varclass}; |
129
|
1
|
50
|
|
|
|
4
|
push(@varnames,map { $Config->{fieldvarprefix}.$_ } @{$Config->{fields}}) if $Config->{options}->{varfields}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
130
|
|
|
|
|
|
|
# Can't do varargs, because I don't know what the args will be in advance! |
131
|
1
|
50
|
|
|
|
3
|
eval 'package '.$package.'; use vars qw('.join(" ",map { s{^(?![\%\$\@])}{\$}; $_ } @varnames).');' if @varnames; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
132
|
1
|
|
|
|
|
153
|
1; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub Method { |
136
|
0
|
|
|
0
|
0
|
0
|
my ($package, $symbol, $referent, $attr, $data, $stage) = @_; |
137
|
1
|
|
|
1
|
|
9
|
no warnings 'redefine'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
55
|
|
138
|
1
|
|
|
1
|
|
5
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1717
|
|
139
|
0
|
|
|
|
|
0
|
if (0 and defined($symbol) and *{$symbol}{NAME} eq 'ANON') { |
140
|
|
|
|
|
|
|
# ^--- DISABLED! |
141
|
|
|
|
|
|
|
# Darn, need to find a better symbol. (Probably :Method is not on the first prototype...) |
142
|
|
|
|
|
|
|
#XXX: This doesn't work. Even $referent points to the wrong thing :( |
143
|
|
|
|
|
|
|
# Can't figure out true name, can't figure out true reference = can't put Humpty Dumpty back together again :( |
144
|
|
|
|
|
|
|
($symbol) = eval 'grep { *{$_}{NAME} ne "ANON" } grep { *{$_}{CODE} and *{$_}{CODE} eq $referent } values %'.$package.'::'; |
145
|
|
|
|
|
|
|
} |
146
|
0
|
0
|
0
|
|
|
0
|
if (not defined($symbol) or *{$symbol}{NAME} eq 'ANON') { |
|
0
|
|
|
|
|
0
|
|
147
|
0
|
|
|
|
|
0
|
require Carp; |
148
|
0
|
|
|
|
|
0
|
local $Carp::CarpLevel = 3; |
149
|
0
|
0
|
|
|
|
0
|
if ($^S) { |
150
|
0
|
|
|
|
|
0
|
Carp::croak "Unable to identify the name of subroutine at $referent. You appear to be calling this inside an eval. This is a known bug - please \"use\" this module at the start of your application.\n"; |
151
|
|
|
|
|
|
|
} else { |
152
|
0
|
|
|
|
|
0
|
Carp::croak "Unable to identify the name of subroutine at $referent. Please ensure :Method is on the first prototype.\n"; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
# Don't try and apply the magic to a closure, this attribute is not set up for it. |
155
|
|
|
|
|
|
|
} |
156
|
0
|
|
|
|
|
0
|
my ($self,@args); |
157
|
0
|
|
0
|
|
|
0
|
my $Config = $Configs{$package}||__DefaultConfigs; |
158
|
0
|
0
|
|
|
|
0
|
$data = "." unless defined $data; |
159
|
0
|
0
|
|
|
|
0
|
if (ref $data) { |
160
|
0
|
|
|
|
|
0
|
($self,@args) = @$data; |
161
|
|
|
|
|
|
|
} else { |
162
|
0
|
|
|
|
|
0
|
($self,@args) = split(/[,\s]+/,$data); |
163
|
|
|
|
|
|
|
} |
164
|
0
|
0
|
|
|
|
0
|
$self = $Config->{this} if $self eq '.'; |
165
|
0
|
|
|
|
|
0
|
$self=~s{^\$}{}; |
166
|
0
|
0
|
|
|
|
0
|
if ($self eq "_") { |
167
|
0
|
|
|
|
|
0
|
$self = ""; |
168
|
0
|
0
|
|
|
|
0
|
$self.= 'local $_ = (ref($_[0]) and UNIVERSAL::isa($_[0],q('.$package.')))?shift:$_; my $me = $_;' if $Config->{options}->{varthis}; |
169
|
0
|
0
|
|
|
|
0
|
$self.= 'my $me = shift;' unless $Config->{options}->{varthis}; |
170
|
0
|
0
|
|
|
|
0
|
$self.= 'local ${^__} = $me;' if $Config->{options}->{hatthis}; |
171
|
0
|
0
|
|
|
|
0
|
$self.= 'local $_ = (ref($_[0]) and UNIVERSAL::isa($_[0],q('.$package.')))?shift:$_; my $me = $_;' unless $self; |
172
|
|
|
|
|
|
|
} else { |
173
|
0
|
|
|
|
|
0
|
my $selfname = $self; |
174
|
0
|
|
|
|
|
0
|
$self = 'my $me = shift;'; |
175
|
0
|
0
|
|
|
|
0
|
$self.='local *'.$package.'::'.$selfname.' = sub { $me };' if $Config->{options}->{subthis}; |
176
|
0
|
0
|
|
|
|
0
|
$self.='local ${^_'.$selfname.'} = $me;' if $Config->{options}->{hatthis}; |
177
|
0
|
0
|
|
|
|
0
|
$self.='local *'.$package.'::'.$selfname.' = \$me;' if $Config->{options}->{varthis}; |
178
|
|
|
|
|
|
|
#$self = 'my $me = $_[0]; local *'.$package.'::'.$self.' = sub { $me }; local ${^_'.$self.'} = $_[0]; local *'.$package.'::'.$self.' = \shift;' |
179
|
|
|
|
|
|
|
} |
180
|
0
|
|
|
|
|
0
|
if (0) { # This is all too late. Needed to do it in BEGIN if I was going to do it at all. |
181
|
|
|
|
|
|
|
my @varargs = @args; |
182
|
|
|
|
|
|
|
eval 'package '.$package.'; use vars qw('.join(" ",grep { $_ ne "_" } map { s{^(?![\%\$\@])}{\$}; $_ } @varargs).');' if @varargs; |
183
|
|
|
|
|
|
|
} |
184
|
0
|
|
|
|
|
0
|
for (@args) { |
185
|
0
|
|
|
|
|
0
|
my $aname = $_; |
186
|
0
|
0
|
0
|
|
|
0
|
if ($aname=~/^\@(\w+)$/ and $aname eq $args[-1]) { |
187
|
0
|
|
|
|
|
0
|
$aname = $1; |
188
|
0
|
|
|
|
|
0
|
$_ = ''; # This alters @args! |
189
|
0
|
0
|
|
|
|
0
|
$_.= 'local @{^_'.$aname.'} = @_;' if $Config->{options}->{hatargs}; |
190
|
0
|
0
|
|
|
|
0
|
$_.= 'my @args = @_; local *'.$package.'::'.$aname.' = \@args;' if $Config->{options}->{varargs}; |
191
|
0
|
|
|
|
|
0
|
next; |
192
|
|
|
|
|
|
|
} |
193
|
0
|
0
|
0
|
|
|
0
|
if ($aname=~/^\%(\w+)$/ and $aname eq $args[-1]) { |
194
|
0
|
|
|
|
|
0
|
$aname = $1; |
195
|
0
|
|
|
|
|
0
|
$_ = ''; # This alters @args! |
196
|
0
|
0
|
|
|
|
0
|
$_.= 'local %{^_'.$aname.'} = @_;' if $Config->{options}->{hatargs}; |
197
|
0
|
0
|
|
|
|
0
|
$_.= 'my %args = @_; local *'.$package.'::'.$aname.' = \%args;' if $Config->{options}->{varargs}; |
198
|
0
|
|
|
|
|
0
|
next; |
199
|
|
|
|
|
|
|
} |
200
|
0
|
|
|
|
|
0
|
$aname=~s{^\$}{}; # Allow, but ignore leading dollar sigal. |
201
|
0
|
0
|
|
|
|
0
|
unless ($aname=~/^\w+$/) { |
202
|
0
|
|
|
|
|
0
|
require Carp; |
203
|
0
|
|
|
|
|
0
|
local $Carp::CarpLevel = 1; |
204
|
0
|
|
|
|
|
0
|
Carp::croak "Bad argument name: $aname (@args)"; |
205
|
|
|
|
|
|
|
} |
206
|
0
|
|
|
|
|
0
|
$_ = ''; # This alters @args! |
207
|
0
|
0
|
|
|
|
0
|
if ($aname eq '_') { |
208
|
0
|
|
|
|
|
0
|
$_.='local $_ = $_[0];'; |
209
|
|
|
|
|
|
|
} else { |
210
|
0
|
0
|
|
|
|
0
|
$_.='local ${^_'.$aname.'} = $_[0];' if $Config->{options}->{hatargs}; |
211
|
0
|
0
|
|
|
|
0
|
$_.='local *'.$package.'::'.$aname.' = \$_[0];' if $Config->{options}->{varargs}; |
212
|
|
|
|
|
|
|
} |
213
|
0
|
|
|
|
|
0
|
$_.='shift;'; |
214
|
|
|
|
|
|
|
} |
215
|
0
|
|
|
|
|
0
|
my @fields = @{$Config->{allfields}}; |
|
0
|
|
|
|
|
0
|
|
216
|
0
|
|
|
|
|
0
|
for (@fields) { |
217
|
0
|
|
|
|
|
0
|
my $fname = $_; |
218
|
0
|
|
|
|
|
0
|
$_ = ""; |
219
|
0
|
0
|
|
|
|
0
|
$_.='local *{^_'.$Config->{fieldhatprefix}.$fname.'} = \$me->{q('.$fname.')};' if $Config->{options}->{hatfields}; |
220
|
0
|
0
|
|
|
|
0
|
$_.='local *'.$package.'::'.$Config->{fieldvarprefix}.$fname.' = \$me->{q('.$fname.')};' if $Config->{options}->{varfields}; |
221
|
|
|
|
|
|
|
} |
222
|
0
|
|
|
|
|
0
|
my $proto = prototype $referent; |
223
|
0
|
0
|
|
|
|
0
|
if (defined $proto) { |
224
|
0
|
|
|
|
|
0
|
$proto = "($proto)"; |
225
|
|
|
|
|
|
|
} else { |
226
|
0
|
|
|
|
|
0
|
$proto = ""; |
227
|
|
|
|
|
|
|
} |
228
|
0
|
0
|
|
|
|
0
|
if ($Config->{options}->{debug}) { |
229
|
0
|
|
|
|
|
0
|
my $subdecl = "sub ".$package."::".(*{$symbol}{NAME}).$proto." {\n\t$self\n\t@fields\n\t@args\n\t\$referent->(\@_)\n};\n"; |
|
0
|
|
|
|
|
0
|
|
230
|
0
|
|
|
|
|
0
|
$subdecl=~s{;(?!\n)\s*}{;\n\t}gs; |
231
|
0
|
|
|
|
|
0
|
warn $subdecl; |
232
|
|
|
|
|
|
|
} |
233
|
0
|
|
|
|
|
0
|
local $@; |
234
|
0
|
|
|
|
|
0
|
my $subdecl = "package $package; sub $proto { |
235
|
|
|
|
|
|
|
$self |
236
|
|
|
|
|
|
|
@fields |
237
|
|
|
|
|
|
|
@args |
238
|
|
|
|
|
|
|
\$referent->(\@_) |
239
|
|
|
|
|
|
|
};"; |
240
|
|
|
|
|
|
|
#*{$symbol} = eval $subdecl; |
241
|
|
|
|
|
|
|
#die $@."\n$subdecl" if $@; |
242
|
0
|
|
|
|
|
0
|
my $subref = eval $subdecl; |
243
|
0
|
0
|
|
|
|
0
|
die "Failure to create sub: ".$@."\n$subdecl" if $@; |
244
|
0
|
|
|
|
|
0
|
my ($sympkg,$symname) = (*{$symbol}{PACKAGE},*{$symbol}{NAME}); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
245
|
|
|
|
|
|
|
# eval '*{$symbol} = $subref; 1' or warn "Assigning symbol: $@"; # I don't know why this doesn't work any more. |
246
|
0
|
0
|
|
|
|
0
|
eval '$'.$sympkg.'::{$symname} = $subref' or die "Failed to assign symbol *{$symbol}{PACKAGE}::*{$symbol}{NAME}: $@"; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
sub ClassMethod { |
250
|
0
|
|
|
0
|
0
|
0
|
my ($package, $symbol, $referent, $attr, $data, $stage) = @_; |
251
|
1
|
|
|
1
|
|
7
|
no warnings 'redefine'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
38
|
|
252
|
1
|
|
|
1
|
|
13
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1755
|
|
253
|
0
|
|
|
|
|
0
|
if (0 and defined($symbol) and *{$symbol}{NAME} eq 'ANON') { |
254
|
|
|
|
|
|
|
# ^--- DISABLED! |
255
|
|
|
|
|
|
|
# Darn, need to find a better symbol. (Probably :Method is not on the first prototype...) |
256
|
|
|
|
|
|
|
#XXX: This doesn't work. Even $referent points to the wrong thing :( |
257
|
|
|
|
|
|
|
# Can't figure out true name, can't figure out true reference = can't put Humpty Dumpty back together again :( |
258
|
|
|
|
|
|
|
($symbol) = eval 'grep { *{$_}{NAME} ne "ANON" } grep { *{$_}{CODE} and *{$_}{CODE} eq $referent } values %'.$package.'::'; |
259
|
|
|
|
|
|
|
} |
260
|
0
|
0
|
0
|
|
|
0
|
if (not defined($symbol) or *{$symbol}{NAME} eq 'ANON') { |
|
0
|
|
|
|
|
0
|
|
261
|
0
|
|
|
|
|
0
|
require Carp; |
262
|
0
|
|
|
|
|
0
|
local $Carp::CarpLevel = 3; |
263
|
0
|
0
|
|
|
|
0
|
if ($^S) { |
264
|
0
|
|
|
|
|
0
|
Carp::croak "Unable to identify the name of subroutine at $referent. You appear to be calling this inside an eval. This is a known bug - please \"use\" this module at the start of your application.\n"; |
265
|
|
|
|
|
|
|
} else { |
266
|
0
|
|
|
|
|
0
|
Carp::croak "Unable to identify the name of subroutine at $referent. Please ensure :Method is on the first prototype.\n"; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
# Don't try and apply the magic to a closure, this attribute is not set up for it. |
269
|
|
|
|
|
|
|
} |
270
|
0
|
|
|
|
|
0
|
my ($class,@args); |
271
|
0
|
|
0
|
|
|
0
|
my $Config = $Configs{$package}||__DefaultConfigs; |
272
|
0
|
0
|
|
|
|
0
|
$data = "." unless defined $data; |
273
|
0
|
0
|
|
|
|
0
|
if (ref $data) { |
274
|
0
|
|
|
|
|
0
|
($class,@args) = @$data; |
275
|
|
|
|
|
|
|
} else { |
276
|
0
|
|
|
|
|
0
|
($class,@args) = split(/[,\s]+/,$data); |
277
|
|
|
|
|
|
|
} |
278
|
0
|
0
|
|
|
|
0
|
$class = $Config->{class} if $class eq '.'; |
279
|
0
|
|
|
|
|
0
|
my $self = $Config->{this}; |
280
|
0
|
|
|
|
|
0
|
$class=~s{^\$}{}; |
281
|
0
|
|
|
|
|
0
|
$self=~s{^\$}{}; |
282
|
0
|
0
|
|
|
|
0
|
if ($self eq "_") { |
283
|
0
|
|
|
|
|
0
|
$self = ""; |
284
|
0
|
0
|
|
|
|
0
|
$self.= 'local $_ = (ref($_[0]) and UNIVERSAL::isa($_[0],q('.$package.')))?shift:$_; my $me = $_;' if $Config->{options}->{varthis}; |
285
|
0
|
0
|
|
|
|
0
|
$self.= 'my $me = shift;' unless $Config->{options}->{varthis}; |
286
|
0
|
0
|
|
|
|
0
|
$self.= 'local ${^__} = $me;' if $Config->{options}->{hatthis}; |
287
|
0
|
0
|
|
|
|
0
|
$self.= 'local $_ = (ref($_[0]) and UNIVERSAL::isa($_[0],q('.$package.')))?shift:$_; my $me = $_;' unless $self; |
288
|
|
|
|
|
|
|
} else { |
289
|
0
|
|
|
|
|
0
|
my $selfname = $self; |
290
|
0
|
|
|
|
|
0
|
$self = 'my $me = shift;'; |
291
|
0
|
0
|
|
|
|
0
|
$self.='local *'.$package.'::'.$selfname.' = sub { $me };' if $Config->{options}->{subthis}; |
292
|
0
|
0
|
|
|
|
0
|
$self.='local ${^_'.$selfname.'} = $me;' if $Config->{options}->{hatthis}; |
293
|
0
|
0
|
|
|
|
0
|
$self.='local *'.$package.'::'.$selfname.' = \$me;' if $Config->{options}->{varthis}; |
294
|
|
|
|
|
|
|
#$self = 'my $me = $_[0]; local *'.$package.'::'.$self.' = sub { $me }; local ${^_'.$self.'} = $_[0]; local *'.$package.'::'.$self.' = \shift;' |
295
|
|
|
|
|
|
|
} |
296
|
0
|
0
|
|
|
|
0
|
if ($class eq "_") { |
297
|
0
|
|
|
|
|
0
|
$class = ""; |
298
|
0
|
0
|
|
|
|
0
|
$class.= 'local $_ = ref($me)||$me;' if $Config->{options}->{varthis}; |
299
|
0
|
0
|
|
|
|
0
|
$class.= 'local ${^__} = $me;' if $Config->{options}->{hatthis}; |
300
|
0
|
0
|
|
|
|
0
|
$class.= 'local $_ = ref($me)||$me;' unless $class; |
301
|
|
|
|
|
|
|
} else { |
302
|
0
|
|
|
|
|
0
|
my $classname = $class; |
303
|
0
|
|
|
|
|
0
|
$class = 'my $class = ref($me)||$me;'; |
304
|
0
|
0
|
|
|
|
0
|
$class.='local *'.$package.'::'.$classname.' = sub { $class };' if $Config->{options}->{subclass}; |
305
|
0
|
0
|
|
|
|
0
|
$class.='local ${^_'.$classname.'} = $class;' if $Config->{options}->{hatclass}; |
306
|
0
|
0
|
|
|
|
0
|
$class.='local *'.$package.'::'.$classname.' = \$class;' if $Config->{options}->{varclass}; |
307
|
|
|
|
|
|
|
} |
308
|
0
|
|
|
|
|
0
|
for (@args) { |
309
|
0
|
|
|
|
|
0
|
my $aname = $_; |
310
|
0
|
0
|
0
|
|
|
0
|
if ($aname=~/^\@(\w+)$/ and $aname eq $args[-1]) { |
311
|
0
|
|
|
|
|
0
|
$aname = $1; |
312
|
0
|
|
|
|
|
0
|
$_ = ''; |
313
|
0
|
0
|
|
|
|
0
|
$_.= 'local @{^_'.$aname.'} = @_;' if $Config->{options}->{hatargs}; |
314
|
0
|
0
|
|
|
|
0
|
$_.= 'my @args = @_; local *'.$package.'::'.$aname.' = \@args;' if $Config->{options}->{varargs}; |
315
|
0
|
|
|
|
|
0
|
next; |
316
|
|
|
|
|
|
|
} |
317
|
0
|
0
|
0
|
|
|
0
|
if ($aname=~/^\%(\w+)$/ and $aname eq $args[-1]) { |
318
|
0
|
|
|
|
|
0
|
$aname = $1; |
319
|
0
|
|
|
|
|
0
|
$_ = ''; |
320
|
0
|
0
|
|
|
|
0
|
$_.= 'local %{^_'.$aname.'} = @_;' if $Config->{options}->{hatargs}; |
321
|
0
|
0
|
|
|
|
0
|
$_.= 'my %args = @_; local *'.$package.'::'.$aname.' = \%args;' if $Config->{options}->{varargs}; |
322
|
0
|
|
|
|
|
0
|
next; |
323
|
|
|
|
|
|
|
} |
324
|
0
|
|
|
|
|
0
|
$aname=~s{^\$}{}; # Allow, but ignore leading dollar sigal. |
325
|
0
|
0
|
|
|
|
0
|
unless ($aname=~/^\w+$/) { |
326
|
0
|
|
|
|
|
0
|
require Carp; |
327
|
0
|
|
|
|
|
0
|
local $Carp::CarpLevel = 1; |
328
|
0
|
|
|
|
|
0
|
Carp::croak "Bad argument name: $aname (@args)"; |
329
|
|
|
|
|
|
|
} |
330
|
0
|
|
|
|
|
0
|
$_ = ''; # This alters @args! |
331
|
0
|
0
|
|
|
|
0
|
if ($aname eq '_') { |
332
|
0
|
|
|
|
|
0
|
$_.='local $_ = $_[0];'; |
333
|
|
|
|
|
|
|
} else { |
334
|
0
|
0
|
|
|
|
0
|
$_.='local ${^_'.$aname.'} = $_[0];' if $Config->{options}->{hatargs}; |
335
|
0
|
0
|
|
|
|
0
|
$_.='local *'.$package.'::'.$aname.' = \$_[0];' if $Config->{options}->{varargs}; |
336
|
|
|
|
|
|
|
} |
337
|
0
|
|
|
|
|
0
|
$_.='shift;'; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
# Class methods don't get fields (you have the {this} variable). |
340
|
|
|
|
|
|
|
# my @fields = @{$Config->{fields}}; |
341
|
|
|
|
|
|
|
# for (@fields) { |
342
|
|
|
|
|
|
|
# my $fname = $_; |
343
|
|
|
|
|
|
|
# $_ = ""; |
344
|
|
|
|
|
|
|
# $_.='local ${^_'.$fname.'} = $me->{q('.$fname.')};' if $Config->{options}->{hatfields}; |
345
|
|
|
|
|
|
|
# $_.='local *'.$package.'::'.$fname.' = \$me->{q('.$fname.')};' if $Config->{options}->{varfields}; |
346
|
|
|
|
|
|
|
# } |
347
|
0
|
|
|
|
|
0
|
my $proto = prototype $referent; |
348
|
0
|
0
|
|
|
|
0
|
if (defined $proto) { |
349
|
0
|
|
|
|
|
0
|
$proto = "($proto)"; |
350
|
|
|
|
|
|
|
} else { |
351
|
0
|
|
|
|
|
0
|
$proto = ""; |
352
|
|
|
|
|
|
|
} |
353
|
0
|
0
|
|
|
|
0
|
if ($Config->{options}->{debug}) { |
354
|
0
|
|
|
|
|
0
|
my $subdecl = "sub ".$package."::".(*{$symbol}{NAME}).$proto." {\n\t$self\n\t$class\n\t@args\n\t\$referent->(\@_)\n};\n"; |
|
0
|
|
|
|
|
0
|
|
355
|
0
|
|
|
|
|
0
|
$subdecl=~s{;(?!\n)\s*}{;\n\t}gs; |
356
|
0
|
|
|
|
|
0
|
warn $subdecl; |
357
|
|
|
|
|
|
|
} |
358
|
0
|
|
|
|
|
0
|
local $@; |
359
|
0
|
|
|
|
|
0
|
my $subdecl = "package $package; sub $proto { |
360
|
|
|
|
|
|
|
$self |
361
|
|
|
|
|
|
|
$class |
362
|
|
|
|
|
|
|
@args |
363
|
|
|
|
|
|
|
\$referent->(\@_) |
364
|
|
|
|
|
|
|
};"; |
365
|
0
|
|
|
|
|
0
|
my $subref = eval $subdecl; |
366
|
0
|
0
|
|
|
|
0
|
die "Failure to create sub: ".$@."\n$subdecl" if $@; |
367
|
0
|
|
|
|
|
0
|
my ($sympkg,$symname) = (*{$symbol}{PACKAGE},*{$symbol}{NAME}); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
368
|
|
|
|
|
|
|
# eval '*{$symbol} = $subref; 1' or warn "Assigning symbol: $@"; # I don't know why this doesn't work any more. |
369
|
0
|
0
|
|
|
|
0
|
eval '$'.$sympkg.'::{$symname} = $subref' or die "Failed to assign symbol *{$symbol}{PACKAGE}::*{$symbol}{NAME}: $@"; |
370
|
|
|
|
|
|
|
# *{$symbol} = eval "package $package; sub $proto { |
371
|
|
|
|
|
|
|
# $self |
372
|
|
|
|
|
|
|
# $class |
373
|
|
|
|
|
|
|
# @args |
374
|
|
|
|
|
|
|
# \$referent->(\@_) |
375
|
|
|
|
|
|
|
# };"; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
our %Methods; |
379
|
|
|
|
|
|
|
our %ClassMethods; |
380
|
|
|
|
|
|
|
our %symcache; |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub findsym($$) { |
383
|
0
|
|
|
0
|
0
|
0
|
my ($pkg,$ref) = @_; |
384
|
0
|
0
|
0
|
|
|
0
|
return $symcache{$pkg,$ref} if $symcache{$pkg,$ref} and *{$symcache{$pkg,$ref}}{CODE} eq $ref; |
|
0
|
|
|
|
|
0
|
|
385
|
1
|
|
|
1
|
|
6
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
537
|
|
386
|
0
|
|
|
|
|
0
|
for (values %{$pkg."::"}) { |
|
0
|
|
|
|
|
0
|
|
387
|
0
|
0
|
0
|
|
|
0
|
return $symcache{$pkg,$ref} = $_ if *{$_}{CODE} and *{$_}{CODE} eq $ref; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
388
|
|
|
|
|
|
|
} |
389
|
0
|
|
|
|
|
0
|
return undef; # Don't cache incase there is a better way to get it later. |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub make_methods($); |
393
|
|
|
|
|
|
|
sub make_methods($) { |
394
|
0
|
|
|
0
|
0
|
0
|
my $pkg = shift; |
395
|
|
|
|
|
|
|
# My call line looks like this to maintain Attribute::Handlers compatibility. |
396
|
|
|
|
|
|
|
# unfortunately I cannot use Attribute::Handlers because it fails to trigger |
397
|
|
|
|
|
|
|
# if you do "eval 'use mypkg;'" and it can't find the symbols. |
398
|
|
|
|
|
|
|
#my ($package, $symbol, $referent, $attr, $data, $stage); |
399
|
0
|
|
|
|
|
0
|
my @oa = $pkg->NEXT::ELSEWHERE::ancestors; |
400
|
0
|
|
0
|
|
|
0
|
1 while @oa and shift(@oa) ne $pkg; |
401
|
0
|
|
0
|
|
|
0
|
1 while @oa and shift(@oa) ne "Class::MethodVars::_ATTRS"; |
402
|
0
|
|
|
|
|
0
|
my $next; |
403
|
0
|
0
|
|
|
|
0
|
if (@oa) { |
404
|
0
|
|
|
|
|
0
|
make_methods(shift(@oa)); |
405
|
|
|
|
|
|
|
} |
406
|
0
|
0
|
|
|
|
0
|
for my $data (@{$ClassMethods{$pkg}||[]}) { |
|
0
|
|
|
|
|
0
|
|
407
|
0
|
|
|
|
|
0
|
my ($package,$ref,$args) = @$data; |
408
|
0
|
|
|
|
|
0
|
my $sym = findsym($package,$ref); |
409
|
0
|
|
|
|
|
0
|
ClassMethod($package,$sym,$ref,"ClassMethod",$args,"import"); |
410
|
|
|
|
|
|
|
} |
411
|
0
|
0
|
|
|
|
0
|
for my $data (@{$Methods{$pkg}||[]}) { |
|
0
|
|
|
|
|
0
|
|
412
|
0
|
|
|
|
|
0
|
my ($package,$ref,$args) = @$data; |
413
|
0
|
|
|
|
|
0
|
my $sym = findsym($package,$ref); |
414
|
0
|
|
|
|
|
0
|
Method($package,$sym,$ref,"ClassMethod",$args,"import"); |
415
|
|
|
|
|
|
|
} |
416
|
0
|
|
|
|
|
0
|
delete $ClassMethods{$pkg}; |
417
|
0
|
|
|
|
|
0
|
delete $Methods{$pkg}; |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
{ |
421
|
1
|
|
|
1
|
|
5
|
no warnings 'void'; # "Too late to run INIT block" |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
118
|
|
422
|
|
|
|
|
|
|
INIT { |
423
|
|
|
|
|
|
|
make_methods($_) for keys %ClassMethods; |
424
|
|
|
|
|
|
|
make_methods($_) for keys %Methods; |
425
|
|
|
|
|
|
|
}; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
package Class::MethodVars::_ATTRS; |
429
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
36
|
|
430
|
1
|
|
|
1
|
|
4
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
27
|
|
431
|
|
|
|
|
|
|
|
432
|
1
|
|
|
1
|
|
5
|
use NEXT; # Need this incase they used to inherit from someone else. |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
745
|
|
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub import { |
435
|
0
|
|
|
0
|
|
0
|
my ($spkg,@args) = @_; |
436
|
0
|
|
|
|
|
0
|
my $tpkg = caller; |
437
|
0
|
0
|
|
|
|
0
|
if ($spkg eq __PACKAGE__) { |
438
|
0
|
|
|
|
|
0
|
require Carp; |
439
|
0
|
|
|
|
|
0
|
Carp::croak "Don't do that."; |
440
|
|
|
|
|
|
|
} |
441
|
0
|
|
|
|
|
0
|
Class::MethodVars::make_methods($spkg); |
442
|
0
|
|
|
|
|
0
|
my @oa = $_[0]->NEXT::ELSEWHERE::ancestors; |
443
|
0
|
|
0
|
|
|
0
|
1 while @oa and shift(@oa) ne $tpkg; |
444
|
0
|
|
0
|
|
|
0
|
1 while @oa and shift(@oa) ne __PACKAGE__; |
445
|
0
|
|
|
|
|
0
|
my $next; |
446
|
0
|
0
|
0
|
|
|
0
|
if (@oa and $next = $oa[0]->can("import")) { |
447
|
0
|
|
|
|
|
0
|
goto &$next; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub MODIFY_CODE_ATTRIBUTES { |
452
|
1
|
|
|
1
|
|
42
|
my ($pkg,$ref,@attrs) = @_; |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# I want to write this: |
455
|
|
|
|
|
|
|
# my @oldattrs = @attrs; |
456
|
|
|
|
|
|
|
# unless (eval q{ @attrs = $pkg->NEXT::DISTINCT::ACTUAL::MODIFY_CODE_ATTRIBUTES($ref,@attrs); 1 }) { |
457
|
|
|
|
|
|
|
# @attrs = @oldattrs; |
458
|
|
|
|
|
|
|
# } |
459
|
|
|
|
|
|
|
# But "(eval)" can't call NEXT...MODIFY_CODE_ATTRIBUTES! So: |
460
|
1
|
|
|
|
|
11
|
my @oa = $_[0]->NEXT::ELSEWHERE::ancestors; |
461
|
1
|
|
66
|
|
|
43
|
1 while @oa and shift(@oa) ne caller; |
462
|
1
|
|
33
|
|
|
5
|
1 while @oa and shift(@oa) ne __PACKAGE__; |
463
|
1
|
|
|
|
|
2
|
my $next; |
464
|
1
|
50
|
33
|
|
|
6
|
if (@oa and $next = $oa[0]->can("import")) { |
465
|
0
|
|
|
|
|
0
|
@attrs = $pkg->$next($ref,@attrs); |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
# End whinge |
468
|
|
|
|
|
|
|
|
469
|
1
|
|
|
|
|
2
|
my @bad_attrs; |
470
|
|
|
|
|
|
|
my @good_attrs; |
471
|
1
|
|
|
|
|
3
|
for (@attrs) { |
472
|
1
|
50
|
|
|
|
10
|
if (/\A(?:Class)?Method(?:\(.*)?\z/) { |
473
|
1
|
|
|
|
|
4
|
push(@good_attrs,$_); |
474
|
|
|
|
|
|
|
} else { |
475
|
0
|
|
|
|
|
0
|
push(@bad_attrs,$_); |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
} |
478
|
1
|
50
|
|
|
|
8
|
if (@good_attrs > 1) { |
|
|
50
|
|
|
|
|
|
479
|
0
|
|
|
|
|
0
|
require Carp; |
480
|
0
|
|
|
|
|
0
|
Carp::croak q{Please only use one of :Method or :ClassMethod for each method}; |
481
|
|
|
|
|
|
|
} elsif (@good_attrs) { |
482
|
1
|
|
|
|
|
2
|
my $args; |
483
|
1
|
50
|
|
|
|
4
|
$args = [split(/[\s,]/,$1)] if $good_attrs[0]=~/\((.*)\)\s*\z/; |
484
|
1
|
50
|
|
|
|
7
|
if ($good_attrs[0]=~/\AClassMethod/) { |
485
|
1
|
|
50
|
|
|
9
|
$ClassMethods{$pkg}||=[]; |
486
|
1
|
|
|
|
|
2
|
push(@{$ClassMethods{$pkg}},[ $pkg,$ref,$args ]); |
|
1
|
|
|
|
|
4
|
|
487
|
|
|
|
|
|
|
} else { |
488
|
0
|
|
0
|
|
|
0
|
$Methods{$pkg}||=[]; |
489
|
0
|
|
|
|
|
0
|
push(@{$Methods{$pkg}},[ $pkg,$ref,$args ]); |
|
0
|
|
|
|
|
0
|
|
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
} |
492
|
1
|
|
|
|
|
4
|
return @bad_attrs; |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
package Class::MethodVars::_Private; |
496
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
25
|
|
497
|
1
|
|
|
1
|
|
11
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
384
|
|
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
sub unique(@) { |
500
|
2
|
|
|
2
|
|
6
|
my %u = map { $_=>$_ } @_; |
|
0
|
|
|
|
|
0
|
|
501
|
2
|
|
|
|
|
7
|
return values %u; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
sub retrFields($) { |
505
|
1
|
|
|
1
|
|
2
|
my $pkg = shift; |
506
|
1
|
50
|
|
|
|
5
|
return () unless $Class::MethodVars::Configs{$pkg}; |
507
|
1
|
50
|
|
|
|
4
|
return () unless $Class::MethodVars::Configs{$pkg}->{fields}; |
508
|
1
|
|
|
|
|
2
|
return @{$Class::MethodVars::Configs{$pkg}->{fields}}; |
|
1
|
|
|
|
|
3
|
|
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
sub findBaseFields($); |
512
|
|
|
|
|
|
|
sub findBaseFields($) { |
513
|
1
|
|
|
1
|
|
2
|
my $pkg = shift; |
514
|
1
|
|
|
|
|
79
|
my @isa = eval '@'.$pkg.'::ISA'; |
515
|
1
|
|
|
|
|
3
|
my @fields; |
516
|
1
|
|
|
|
|
3
|
for my $bpkg (@isa) { |
517
|
0
|
|
|
|
|
0
|
push(@fields,findBaseFields($bpkg)); |
518
|
|
|
|
|
|
|
} |
519
|
1
|
|
|
|
|
3
|
return unique @fields,retrFields $pkg; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
1; |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
__END__ |