File Coverage

blib/lib/Safe/World/Scope.pm
Criterion Covered Total %
statement 103 168 61.3
branch 30 114 26.3
condition 4 12 33.3
subroutine 16 19 84.2
pod 6 8 75.0
total 159 321 49.5


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: Scope.pm
3             ## Purpose: Safe::World::Scope
4             ## Author: Graciliano M. P.
5             ## Modified by:
6             ## Created: 15/12/2003
7             ## RCS-ID:
8             ## Copyright: (c) 2003 Graciliano M. P.
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12            
13             package Safe::World::Scope ;
14            
15 1     1   5 use strict qw(vars);
  1         2  
  1         35  
16            
17 1     1   5 use vars qw($VERSION @ISA) ;
  1         1  
  1         59  
18             $VERSION = '0.03' ;
19            
20 1     1   5 no warnings ;
  1         2  
  1         868  
21            
22             my ($HOLE , %HOOK_IDS , %SCOPES_CACHE , %TABLES) ;
23            
24             #######
25             # NEW # package , no_cache , only_call
26             #######
27            
28             sub new {
29 5     5 1 10 my $class = shift ;
30 5         7 my ($package , $no_cache , $only_call) = @_ ;
31            
32 5         13 $package =~ s/[^\w:]//gs ;
33 5         26 $package =~ s/[:\.]+/::/gs ;
34 5         8 $package =~ s/^:+//g ;
35 5         15 $package =~ s/:+$//g ;
36            
37 5 50 33     26 return $SCOPES_CACHE{$package} if ( !$no_cache && $SCOPES_CACHE{$package} ) ;
38            
39 5 50       10 delete $TABLES{$package} if $no_cache ;
40            
41 5         20 my $this = bless({} , $class) ;
42            
43 5         17 $this->{PACKAGE} = $package ;
44            
45 5         10 $this->{HOOK} = new_hook($package,$only_call) ;
46            
47 5         11 $this->{STASH} = $this->_STASH_REF_NOW ;
48            
49 5         8 $SCOPES_CACHE{$package} = $this ;
50            
51 5         14 return $this ;
52             }
53            
54             ##################
55             # _STASH_REF_NOW #
56             ##################
57            
58             sub _STASH_REF_NOW {
59 8     8   11 my $ref = \%{ $_[0]->{PACKAGE} . '::' } ;
  8         37  
60 8         33 return "$ref" ;
61             }
62            
63             ############
64             # NEW_HOOK #
65             ############
66            
67             sub new_hook {
68 5     5 0 7 my $class = shift ;
69 5         6 my $only_call = shift ;
70            
71 5         19 my $this = bless({} , $class) ;
72            
73 5         30 $this->{PACKAGE} = $class ;
74            
75 5         12 my $hook_sub = "$class\::__SAFEWORLD_HOOK__" ;
76            
77 5         5 my $table ;
78 5 50       10 if ( !defined $TABLES{$class} ) {
79 5         14 my @table = &scanpack_table($class) ;
80 5         14 $table = {} ;
81            
82 5         9 foreach my $table_i ( @table ) {
83 133 50       818 if ( $table_i =~ /^([\$\@\%\*\&])(\Q$class\E:*)(.*)/ ) {
84 133         378 my ($tp , $sub , $name) = ($1,"$2$3",$3) ;
85 133 50       242 next if $name eq '__SAFEWORLD_HOOK__' ;
86            
87            
88 133 100       209 if ( $tp eq '&' ) { $table->{$tp}{$name} = \&$sub ;}
  128 50       545  
    0          
    0          
    0          
    0          
89             elsif ( $only_call ) { ; }
90 0         0 elsif ( $tp eq '$' ) { $table->{$tp}{$name} = \$$sub ;}
91 0         0 elsif ( $tp eq '@' ) { $table->{$tp}{$name} = \@$sub ;}
92 0         0 elsif ( $tp eq '%' ) { $table->{$tp}{$name} = \%$sub ;}
93 0         0 elsif ( $tp eq '*' ) { $table->{$tp}{$name} = \&$sub ;}
94             }
95             }
96            
97 5         22 $TABLES{$class} = $table ;
98             }
99 0         0 else { $table = $TABLES{$class} ;}
100            
101 5 50       37 if ( !defined &$hook_sub ) {
102            
103 5         35 *{$hook_sub} = sub {
104 5     5   13 my $hook = shift ;
105 5         21 &__SAFEWORLD_HOOK__($hook,$table,@_) ;
106 5         21 } ;
107            
108             ## Overload DESTROY to skeep DESTROY of HOOKs.
109 5 100       15 if ( $table->{'&'}{DESTROY} ) {
110 3         5 my $dest_ref = \&{"$class\::DESTROY"} ;
  3         11  
111 3 50   3   11 *{"$class\::DESTROY"} = sub { return if $HOOK_IDS{"$_[0]"} ; &$dest_ref(@_) ;}
  3         14  
  3         22  
112 3         11 }
113            
114             }
115            
116 5 50       13 if ( $only_call ) {
117 5         29 $TABLES{$class}{only_call} = "$this" ;
118             }
119            
120 5         13 $HOOK_IDS{"$this"} = 1 ;
121            
122 5         14 return $this ;
123             }
124            
125             ##################
126             # SCANPACK_TABLE # Copy from Safe::World::scanpack_table, since this package need to be scope independent!
127             ##################
128            
129             sub scanpack_table {
130 5     5 0 6 my ( $packname ) = @_ ;
131            
132 5 50       15 $packname .= '::' unless $packname =~ /::$/ ;
133 1     1   6 no strict "refs" ;
  1         2  
  1         51  
134 5         5 my $package = *{$packname}{HASH} ;
  5         56  
135 5 50       22 return unless defined $package ;
136            
137 1     1   10 no warnings ;
  1         2  
  1         1643  
138 5         18 local $^W = 0 ;
139            
140 5         7 my @table ;
141            
142             my $fullname ;
143 5         49 foreach my $symb ( keys %$package ) {
144 168         203 $fullname = "$packname$symb" ;
145 168 100 66     618 if ( $symb !~ /::$/ && $symb !~ /[^\w:]/ ) {
146 158 100       459 if (defined $$fullname) { push(@table , "\$$fullname") ;}
  5         9  
147 158 50       414 if (defined %$fullname) { push(@table , "\%$fullname") ;}
  0         0  
148 158 50       435 if (defined @$fullname) { push(@table , "\@$fullname") ;}
  0         0  
149 158 100       415 if (defined &$fullname) { push(@table , "\&$fullname") ;}
  128         266  
150 158 50 33     215 if (*{$fullname}{IO} && fileno $fullname) {
  158         634  
151 0         0 push(@table , "\*$fullname") ;
152             }
153             }
154             }
155            
156 5         58 return( @table ) ;
157             }
158            
159             ######################
160             # __SAFEWORLD_HOOK__ #
161             ######################
162            
163             sub __SAFEWORLD_HOOK__ {
164 5     5   8 my $__HOOK__ = shift ;
165 5         9 my $__TABLE__ = shift ;
166            
167             ##print main::STDOUT "SCOPE>> @_\n" ;
168            
169 5 50 0     19 if ( $_[0] eq 'call' ) { shift ;
  5 0       7  
    0          
    0          
170 5         6 my $name = shift ;
171 5         15 my $sub = $__TABLE__->{'&'}{$name} ;
172 5 50       31 return &$sub(@_) if $sub ;
173 0         0 die("Undefined subroutine &$__HOOK__->{PACKAGE}\::$name") ;
174 0         0 return undef ;
175             }
176            
177 0         0 elsif ( $__TABLE__->{only_call} && $__TABLE__->{only_call}{"$__HOOK__"} ) { return ;}
178            
179 0         0 elsif ( $_[0] eq 'get' ) { shift ;
180 0 0       0 if ( $_[0] eq '$' ) { return ${ $__TABLE__->{'$'}{$_[1]} } ;}
  0 0       0  
  0 0       0  
    0          
    0          
    0          
    0          
    0          
181 0         0 elsif ( $_[0] eq '@' ) { return @{ $__TABLE__->{'@'}{$_[1]} } ;}
  0         0  
182 0         0 elsif ( $_[0] eq '%' ) { return %{ $__TABLE__->{'%'}{$_[1]} } ;}
  0         0  
183 0         0 elsif ( $_[0] eq '*' ) { return *{ $__TABLE__->{'*'}{$_[1]} } ;}
  0         0  
184 0         0 elsif ( $_[0] eq '\$' ) { return $__TABLE__->{'$'}{$_[1]} ;}
185 0         0 elsif ( $_[0] eq '\@' ) { return $__TABLE__->{'@'}{$_[1]} ;}
186 0         0 elsif ( $_[0] eq '\%' ) { return $__TABLE__->{'%'}{$_[1]} ;}
187 0         0 elsif ( $_[0] eq '\*' ) { return $__TABLE__->{'*'}{$_[1]} ;}
188             }
189            
190 0         0 elsif ( $_[0] eq 'set' ) { shift ;
191 0         0 my $__REF__ = ref($_[2]) ;
192 0 0       0 if ( $_[0] eq '$' ) { return ${ $__TABLE__->{'$'}{$_[1]} } = $__REF__ eq 'SCALAR' ? ${$_[2]} : $__REF__ eq 'ARRAY' ? @{$_[2]} : $__REF__ eq 'HASH' ? %{$_[2]} : $_[2] ;}
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
    0          
193 0 0       0 elsif ( $_[0] eq '@' ) { return @{ $__TABLE__->{'@'}{$_[1]} } = $__REF__ eq 'SCALAR' ? ${$_[2]} : $__REF__ eq 'ARRAY' ? @{$_[2]} : $__REF__ eq 'HASH' ? %{$_[2]} : $_[2] ;}
  0 0       0  
  0 0       0  
  0         0  
  0         0  
194 0 0       0 elsif ( $_[0] eq '%' ) { return %{ $__TABLE__->{'%'}{$_[1]} } = $__REF__ eq 'SCALAR' ? ${$_[2]} : $__REF__ eq 'ARRAY' ? @{$_[2]} : $__REF__ eq 'HASH' ? %{$_[2]} : $_[2] ;}
  0 0       0  
  0 0       0  
  0         0  
  0         0  
195 0 0       0 elsif ( $_[0] eq '*' ) { return *{ $__TABLE__->{'*'}{$_[1]} } = $__REF__ eq 'SCALAR' ? ${$_[2]} : $__REF__ eq 'ARRAY' ? @{$_[2]} : $__REF__ eq 'HASH' ? %{$_[2]} : $_[2] ;}
  0 0       0  
  0 0       0  
  0         0  
  0         0  
196             }
197            
198 0         0 return ;
199             }
200            
201             #######
202             # NEW #
203             #######
204            
205             sub NEW {
206 3     3 1 7 my $this = shift ;
207 3         19 $this->call_hole('new',$this->{PACKAGE},@_) ;
208             }
209            
210             #############
211             # CALL_HOLE #
212             #############
213            
214             sub call_hole {
215 3     3 1 5 my $this = shift ;
216 3         4 my $sub = shift ;
217            
218 3 100       10 &_load_HOLE if !$HOLE ;
219            
220 3 50       35 if ( $this->_STASH_REF_NOW ne $this->{STASH} ) {
221 0         0 my $sub_ref = $TABLES{ $this->{HOOK}->{PACKAGE} }->{'&'}{$sub} ;
222 0 0       0 die("Undefined subroutine &$this->{HOOK}->{PACKAGE}::$sub") if !$sub_ref ;
223 0         0 return $HOLE->call($sub_ref,@_) ;
224             }
225            
226 3         17 return $this->{HOOK}->__SAFEWORLD_HOOK__('call',$sub,@_) ;
227             }
228            
229             ##############
230             # _LOAD_HOLE #
231             ##############
232            
233             sub _load_HOLE {
234 1 50   1   4 if ( !$HOLE ) {
235 1         949 require Safe::World::Hole ;
236 1         16 $HOLE = new Safe::World::Hole ;
237             }
238             }
239            
240             ########
241             # CALL #
242             ########
243            
244             sub call {
245 2     2 1 4 my $this = shift ;
246 2         4 my $sub = shift ;
247 2         7 return $this->{HOOK}->__SAFEWORLD_HOOK__('call',$sub,@_) ;
248             }
249            
250             #######
251             # GET #
252             #######
253            
254             sub get {
255 0     0 1   my $this = shift ;
256 0           my ($tp,$var) = ( $_[0] =~ /^(\\?[\$\@\%\*])(\w+(?:::\w+)*)/ );
257 0           $this->{HOOK}->__SAFEWORLD_HOOK__('get',$tp,$var) ;
258             }
259            
260             #######
261             # SET #
262             #######
263            
264             sub set {
265 0     0 1   my $this = shift ;
266 0           my $toset = shift ;
267 0           my ( undef , $keep_ref ) = @_ ;
268            
269 0           my ($tp,$var) = ( $toset =~ /^(\\?[\$\@\%\*])(\w+(?:::\w+)*)/ ) ;
270            
271 0           my $ref ;
272            
273 0 0         if ( $keep_ref ) { $ref = \$_[0] ;}
  0            
274 0           else { $ref = $_[0] ;}
275            
276 0           $this->{HOOK}->__SAFEWORLD_HOOK__('set',$tp,$var,$ref) ;
277             }
278            
279 0     0     sub DESTROY {}
280            
281             #######
282             # END #
283             #######
284            
285             1;
286            
287             __END__