File Coverage

blib/lib/Class/HPLOO.pm
Criterion Covered Total %
statement 264 408 64.7
branch 75 166 45.1
condition 13 47 27.6
subroutine 16 19 84.2
pod 0 14 0.0
total 368 654 56.2


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: HPLOO.pm
3             ## Purpose: OO-Classes for HPL.
4             ## Author: Graciliano M. P.
5             ## Modified by:
6             ## Created: 30/09/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 Class::HPLOO ;
14            
15 1     1   27 use 5.006 ;
  1         3  
  1         41  
16 1     1   419983 use Filter::Simple ;
  1         757048  
  1         19  
17 1     1   47 use strict ;
  1         1  
  1         32  
18            
19 1     1   4 use vars qw($VERSION $SYNTAX) ;
  1         1  
  1         9653  
20            
21             $VERSION = '0.23';
22            
23             my (%HTML , %COMMENTS , %CLASSES , $SUB_OO , $DUMP , $ALL_OO , $NICE , $NO_CLEAN_ARGS , $ADD_HTML_EVAL , $DO_NOTHING , $BUILD , $BUILD_PM_FILE , $BUILD_PM_VERSION , $USE_BASE , $RET_CACHE , $FIRST_SUB_IDENT , $PREV_CLASS_NAME) ;
24            
25             my (%CACHE , $LOADED) ;
26            
27             ###################################
28            
29             my (%REF_TYPES , $CLASS_NEW , $CLASS_NEW_ATTR , $SUB_AUTO_OO , $SUB_ALL_OO , $SUB_HTML_EVAL , $SUB_ATTR , $USE_BASE_REF) ;
30            
31             if (!$LOADED) {
32            
33             %REF_TYPES = (
34             '$' => 'SCALAR' ,
35             '@' => 'ARRAY' ,
36             '%' => 'HASH' ,
37             '&' => 'CODE' ,
38             '*' => 'GLOB' ,
39             ) ;
40            
41             my $CLASS_EXTRAS = q`
42             sub SUPER {
43             eval('package Class::HPLOO::Base ;') if !defined *{'Class::HPLOO::Base::'} ;
44            
45             my ($prev_pack , undef , undef , $sub0) = caller(1) ;
46             $prev_pack = undef if $prev_pack eq 'Class::HPLOO::Base' ;
47            
48             my ($pack,$sub) = ( $sub0 =~ /^(?:(.*?)::|)(\w+)$/ );
49             my $sub_is_new_hploo = $sub0 =~ /^(.*?(?:::)?$sub)\::$sub$/ ? 1 : undef ;
50            
51             unshift(@_ , $prev_pack) if ( $sub_is_new_hploo && $prev_pack && ((!ref($_[0]) && $_[0] ne $prev_pack && !UNIVERSAL::isa($_[0] , $prev_pack)) || (ref($_[0]) && !UNIVERSAL::isa($_[0] , $prev_pack)) ) ) ;
52            
53             if ( defined @{"$pack\::ISA"} ) {
54             my $isa_sub = ISA_FIND_NEW($pack, ($sub_is_new_hploo?'new':$sub) ,1) ;
55             my ($sub_name) = ( $isa_sub =~ /(\w+)$/gi );
56             if ( $sub0 ne $isa_sub && !ref($_[0]) && $isa_sub =~ /^(.*?(?:::)?$sub_name)\::$sub_name$/ ) {
57             @_ = ( bless({},$_[0]) , @_[1..$#_] ) ;
58             }
59             if ( $sub0 eq $isa_sub && UNIVERSAL::isa($_[0] , $pack) ) {
60             my @isa = Class::HPLOO::Base::FIND_SUPER_WALK( ref($_[0]) , $pack ) ;
61             my $pk = $isa[-1] ;
62             if ( $sub_is_new_hploo ) {
63             if ( UNIVERSAL::isa($pk , 'Class::HPLOO::Base') ) {
64             ($sub) = ( $pk =~ /(\w+)$/gi );
65             }
66             else { $sub = 'new' ;}
67             }
68             my $isa_sub = $pk->can($sub) ;
69             return &$isa_sub( ARGS_WRAPPER(@_) ) if $isa_sub ;
70             }
71             return &$isa_sub(@_) if $isa_sub && defined &$isa_sub && $sub0 ne $isa_sub ;
72             }
73             $sub = $sub_is_new_hploo ? 'new' : $sub ;
74             die("Can't find SUPER method for $sub0!") if "$pack\::$sub" eq $sub0 ;
75             return &{"$pack\::$sub"}(@_) ;
76             }
77            
78             sub FIND_SUPER_WALK {
79             my $class_main = shift ;
80             my $class_end = shift ;
81             my $only_stak = shift ;
82            
83             my (@stack) ;
84             my $stack = $only_stak || {} ;
85            
86             my $found ;
87             foreach my $isa_i ( @{"$class_main\::ISA"} ) {
88             next if $$stack{$isa_i}++ ;
89             $found = 1 if $isa_i eq $class_end ;
90             push(@stack , $isa_i , FIND_SUPER_WALK($isa_i , $class_end , $stack) );
91             }
92            
93             return ($found ? @stack : ()) if $only_stak ;
94             return @stack ;
95             }
96            
97             sub ISA_FIND_NEW {
98             my $pack = shift ;
99             my $sub = shift ;
100             my $look_deep = shift ;
101             my $count = shift ;
102             return if $count > 100 ;
103            
104             my ($sub_name) ;
105             if ( UNIVERSAL::isa($pack , 'Class::HPLOO::Base') ) {
106             ($sub_name) = $sub eq 'new' ? ( $pack =~ /(\w+)$/ ) : ($sub) ;
107             }
108             else { $sub_name = $sub ;}
109            
110             my $isa_sub = "$pack\::$sub_name" ;
111            
112             if ( $look_deep || !defined &$isa_sub ) {
113             foreach my $isa_i ( @{"$pack\::ISA"} ) {
114             next if $isa_i eq $pack || $isa_i eq 'Class::HPLOO::Base' ;
115             last if $isa_i eq 'UNIVERSAL' ;
116             $isa_sub = ISA_FIND_NEW($isa_i , $sub , 0 , $count+1) ;
117             last if $isa_sub ;
118             }
119             }
120            
121             $isa_sub = undef if !defined &$isa_sub ;
122             return $isa_sub ;
123             }
124            
125             sub new_call_BEGIN {
126             my $class = shift ;
127             my $this = $class ;
128             foreach my $ISA_i ( @ISA ) {
129             last if $ISA_i eq 'Class::HPLOO::Base' ;
130             my $ret ;
131             my ($sub) = ( $ISA_i =~ /(\w+)$/ );
132             $sub = "$ISA_i\::$sub\_BEGIN" ;
133             $ret = &$sub($this,@_) if defined &$sub ;
134             $this = $ret if UNIVERSAL::isa($ret,$class) ;
135             }
136             return $this ;
137             }
138            
139             sub new_call_END {
140             my $class = shift ;
141             foreach my $ISA_i ( @ISA ) {
142             last if $ISA_i eq 'Class::HPLOO::Base' ;
143             my $ret ;
144             my ($sub) = ( $ISA_i =~ /(\w+)$/ );
145             $sub = "$ISA_i\::$sub\_END" ;
146             &$sub(@_) if defined &$sub ;
147             }
148             return ;
149             }
150             `;
151            
152             $CLASS_NEW = q`
153             sub new {
154             if ( !defined &%CLASS% && @ISA > 1 ) {
155             foreach my $ISA_i ( @ISA ) {
156             return &{"$ISA_i\::new"}(@_) if defined &{"$ISA_i\::new"} ;
157             }
158             }
159            
160             my $class = shift ; $class = ref($class) if ref($class) ;
161            
162             my $this = new_call_BEGIN($class , @_) ;
163             $this = bless({} , $class) if !ref($this) || !UNIVERSAL::isa($this,$class) ;
164            
165             no warnings ;
166            
167             my $undef = \'' ;
168             sub UNDEF {$undef} ;
169            
170             my $ret_this = defined &%CLASS% ? $this->%CLASS%(@_) : undef ;
171            
172             if ( ref($ret_this) && UNIVERSAL::isa($ret_this,$class) ) { $this = $ret_this }
173             elsif ( $ret_this == $undef ) { $this = undef }
174            
175             new_call_END($class,$this,@_) ;
176            
177             return $this ;
178             }
179            
180             sub CLASS_HPLOO_TIE_KEYS ;
181            
182             ` . $CLASS_EXTRAS ;
183            
184             $CLASS_NEW_ATTR = q`
185             sub new {
186             if ( !defined &%CLASS% && @ISA > 1 ) {
187             foreach my $ISA_i ( @ISA ) {
188             return &{"$ISA_i\::new"}(@_) if defined &{"$ISA_i\::new"} ;
189             }
190             }
191            
192             my $class = shift ; $class = ref($class) if ref($class) ;
193            
194             my $this = new_call_BEGIN($class , @_) ;
195             $this = bless({} , $class) if !ref($this) || !UNIVERSAL::isa($this,$class) ;
196            
197             no warnings ;
198            
199             my $undef = \'' ;
200             sub UNDEF {$undef} ;
201            
202             if ( $CLASS_HPLOO{ATTR} ) { CLASS_HPLOO_TIE_KEYS($this) }
203            
204             my $ret_this = defined &%CLASS% ? $this->%CLASS%(@_) : undef ;
205            
206             if ( ref($ret_this) && UNIVERSAL::isa($ret_this,$class) ) {
207             $this = $ret_this ;
208             if ( $CLASS_HPLOO{ATTR} && UNIVERSAL::isa($this,'HASH') ) { CLASS_HPLOO_TIE_KEYS($this) }
209             }
210             elsif ( $ret_this == $undef ) { $this = undef }
211            
212             new_call_END($this,@_) ;
213            
214             return $this ;
215             }
216            
217             sub CLASS_HPLOO_TIE_KEYS {
218             my $this = shift ;
219             if ( $CLASS_HPLOO{ATTR} ) {
220             foreach my $Key ( keys %{$CLASS_HPLOO{ATTR}} ) {
221             tie( $this->{$Key} => '%PACKAGE%::HPLOO_TIESCALAR' , $this , $Key , $CLASS_HPLOO{ATTR}{$Key}{tp} , $CLASS_HPLOO{ATTR}{$Key}{pr} , \$this->{CLASS_HPLOO_ATTR}{$Key} , \$this->{CLASS_HPLOO_CHANGED} , '%PACKAGE%' ) if !exists $this->{$Key} ;
222             }
223             }
224             }
225            
226             ` . $CLASS_EXTRAS ;
227            
228             $SUB_AUTO_OO = q`
229             my $CLASS_HPLOO ;
230            
231             $CLASS_HPLOO = $this if defined $this ;
232             my $this = ref($_[0]) && UNIVERSAL::isa($_[0],__PACKAGE__) ? shift : $CLASS_HPLOO ;
233             my $CLASS = ref($this) || __PACKAGE__ ;
234            
235             $CLASS_HPLOO = undef ;
236             ` ;
237            
238             $SUB_ALL_OO = q`
239             my $this = ref($_[0]) ? shift : undef ;
240             my $CLASS = ref($this) || __PACKAGE__ ;
241             ` ;
242            
243             ## my $this = ref($_[0]) && UNIVERSAL::isa($_[0],__PACKAGE__) ? shift : undef ;
244            
245             $SUB_HTML_EVAL = q~
246             sub CLASS_HPLOO_HTML {
247             return '' if !$CLASS_HPLOO{HTML}{$_[0]} ;
248             no strict ;
249             return eval( ${$CLASS_HPLOO{HTML}{$_[0]}}[0] . " <
250             return eval("<
251             }
252             ~ ;
253            
254             $SUB_ATTR = q`
255            
256             sub GET_CLASS_HPLOO_HASH { return \%CLASS_HPLOO } ;
257            
258             sub ATTRS { return @{[@{ $CLASS_HPLOO{ATTR_ORDER} }]} } ;
259            
260             sub CLASS_HPLOO_ATTR {
261             my @attrs = split(/\s*,\s*/ , $_[0]) ;
262            
263             foreach my $attrs_i ( @attrs ) {
264             $attrs_i =~ s/^\s+//s ;
265             $attrs_i =~ s/\s+$//s ;
266             my ($name) = ( $attrs_i =~ /(\w+)$/gi ) ;
267             my ($type) = ( $attrs_i =~ /^((?:\w+\s+)*?&?\w+|(?:\w+\s+)*?\w+(?:(?:::|\.)\w+)*)\s+\w+$/gi ) ;
268            
269             my $type0 = $type ;
270             $type0 =~ s/\s+/ /gs ;
271            
272             $type = lc($type) ;
273             $type =~ s/(?:^|\s*)bool$/boolean/gs ;
274             $type =~ s/(?:^|\s*)int$/integer/gs ;
275             $type =~ s/(?:^|\s*)float$/floating/gs ;
276             $type =~ s/(?:^|\s*)str$/string/gs ;
277             $type =~ s/(?:^|\s*)sub$/sub_$name/gs ;
278             $type =~ s/\s//gs ;
279            
280             $type = 'any' if $type !~ /^(?:(?:ref)|(?:ref)?(?:array|hash)(?:boolean|integer|floating|string|sub_\w+|any|&\w+)|(?:ref)?(?:array|hash)|(?:array|hash)?(?:boolean|integer|floating|string|sub_\w+|any|&\w+))$/ ;
281            
282             if ( $type eq 'any' && $type0 =~ /^((?:ref\s*)?(?:array|hash) )?(\w+(?:(?:::|\.)\w+)*)$/ ) {
283             my ($tp1 , $tp2) = ($1 , $2) ;
284             $tp1 =~ s/\s+//gs ;
285             $tp2 = 'UNIVERSAL' if $tp2 =~ /^(?:obj|object)$/i ;
286             $tp2 =~ s/\.+/::/gs ;
287             $type = "$tp1$tp2" ;
288             }
289            
290             my $parse_ref = $type =~ /^(?:array|hash)/ ? 1 : 0 ;
291            
292             push(@{ $CLASS_HPLOO{ATTR_ORDER} } , $name) if !$CLASS_HPLOO{ATTR}{$name} ;
293            
294             $CLASS_HPLOO{ATTR}{$name}{tp} = $type ;
295             $CLASS_HPLOO{ATTR}{$name}{pr} = $parse_ref ;
296            
297             my $return ;
298            
299             if ( $type =~ /^sub_(\w+)$/ ) {
300             my $sub = $1 ;
301             $return = qq~
302             return (&$sub(\$this,\@_))[0] if defined &$sub ;
303             return undef ;
304             ~ ;
305             }
306             else {
307             $return = $parse_ref ? qq~
308             ref(\$this->{CLASS_HPLOO_ATTR}{$name}) eq 'ARRAY' ? \@{\$this->{CLASS_HPLOO_ATTR}{$name}} :
309             ref(\$this->{CLASS_HPLOO_ATTR}{$name}) eq 'HASH' ? \%{\$this->{CLASS_HPLOO_ATTR}{$name}} :
310             \$this->{CLASS_HPLOO_ATTR}{$name}
311             ~ :
312             "\$this->{CLASS_HPLOO_ATTR}{$name}" ;
313             }
314            
315             eval(qq~
316             sub set_$name {
317             my \$this = shift ;
318             if ( !defined \$this->{$name} ) {
319             tie( \$this->{$name} => '%PACKAGE%::HPLOO_TIESCALAR' , \$this , '$name' , '$type' , $parse_ref , \\\\\\$this->{CLASS_HPLOO_ATTR}{$name} , \\\\\\$this->{CLASS_HPLOO_CHANGED} , '%PACKAGE%' ) ;
320             }
321            
322             \$this->{CLASS_HPLOO_CHANGED}{$name} = 1 ;
323             \$this->{CLASS_HPLOO_ATTR}{$name} = CLASS_HPLOO_ATTR_TYPE( ref(\$this) , '$type',\@_) ;
324             }
325             ~) if !defined &{"set_$name"} ;
326            
327             eval(qq~
328             sub get_$name {
329             my \$this = shift ;
330             $return ;
331             }
332             ~) if !defined &{"get_$name"} ;
333             }
334             }
335            
336             { package %PACKAGE%::HPLOO_TIESCALAR ;
337             sub TIESCALAR {
338             shift ;
339             my $obj = shift ;
340             my $this = bless( { nm => $_[0] , tp => $_[1] , pr => $_[2] , rf => $_[3] , rfcg => $_[4] , pk => ($_[5] || scalar caller) } , __PACKAGE__ ) ;
341            
342             if ( $this->{tp} =~ /^sub_(\w+)$/ ) {
343             my $CLASS_HPLOO = %PACKAGE%::GET_CLASS_HPLOO_HASH() ;
344            
345             if ( !ref($$CLASS_HPLOO{OBJ_TBL}) ) {
346             eval { require Hash::NoRef } ;
347             if ( !$@ ) {
348             $$CLASS_HPLOO{OBJ_TBL} = {} ;
349             tie( %{$$CLASS_HPLOO{OBJ_TBL}} , 'Hash::NoRef') ;
350             }
351             else { $@ = undef }
352             }
353            
354             $$CLASS_HPLOO{OBJ_TBL}{ ++$$CLASS_HPLOO{OBJ_TBL}{x} } = $obj ;
355             $this->{oid} = $$CLASS_HPLOO{OBJ_TBL}{x} ;
356             }
357            
358             return $this ;
359             }
360            
361             sub STORE {
362             my $this = shift ;
363             my $ref = $this->{rf} ;
364             my $ref_changed = $this->{rfcg} ;
365            
366             if ( $ref_changed ) {
367             if ( ref $$ref_changed ne 'HASH' ) { $$ref_changed = {} }
368             $$ref_changed->{$this->{nm}} = 1 ;
369             }
370            
371             if ( $this->{pr} ) {
372             my $tp = $this->{tp} =~ /^ref/ ? $this->{tp} : 'ref' . $this->{tp} ;
373             $$ref = &{"$this->{pk}::CLASS_HPLOO_ATTR_TYPE"}($this->{pk} , $tp , @_) ;
374             }
375             else {
376             $$ref = &{"$this->{pk}::CLASS_HPLOO_ATTR_TYPE"}($this->{pk} , $this->{tp} , @_) ;
377             }
378             }
379            
380             sub FETCH {
381             my $this = shift ;
382             my $ref = $this->{rf} ;
383            
384             if ( $this->{tp} =~ /^sub_(\w+)$/ ) {
385             my $CLASS_HPLOO = %PACKAGE%::GET_CLASS_HPLOO_HASH() ;
386             my $sub = $this->{pk} . '::' . $1 ;
387             my $obj = $$CLASS_HPLOO{OBJ_TBL}{ $this->{oid} } ;
388             return (&$sub($obj,@_))[0] if defined &$sub ;
389             }
390             else {
391             if ( $this->{tp} =~ /^(?:ref)?(?:array|hash)/ ) {
392             my $ref_changed = $this->{rfcg} ;
393             if ( $ref_changed ) {
394             if ( ref $$ref_changed ne 'HASH' ) { $$ref_changed = {} }
395             $$ref_changed->{$this->{nm}} = 1 ;
396             }
397             }
398             return $$ref ;
399             }
400             return undef ;
401             }
402             sub UNTIE {}
403             sub DESTROY {}
404             }
405            
406             sub CLASS_HPLOO_ATTR_TYPE {
407             my $class = shift ;
408             my $type = shift ;
409            
410             if ($type eq 'any') { return $_[0] }
411             elsif ($type eq 'string') {
412             return "$_[0]" ;
413             }
414             elsif ($type eq 'boolean') {
415             return if $_[0] =~ /^(?:false|null|undef)$/i ;
416             return 1 if $_[0] ;
417             return ;
418             }
419             elsif ($type eq 'integer') {
420             my $val = $_[0] ;
421             my ($sig) = ( $val =~ /^(-)/ );
422             $val =~ s/[^0-9]//gs ;
423             $val = "$sig$val" ;
424             return $val ;
425             }
426             elsif ($type eq 'floating') {
427             my $val = $_[0] ;
428             $val =~ s/[\s_]+//gs ;
429             if ( $val !~ /^\d+\.\d+$/ ) {
430             ($val) = ( $val =~ /(\d+)/ ) ;
431             $val .= '.0' ;
432             }
433             return $val ;
434             }
435             elsif ($type =~ /^sub_(\w+)$/) {
436             my $sub = $1 ;
437             return (&$sub(@_))[0] if defined &$sub ;
438             }
439             elsif ($type =~ /^&(\w+)$/) {
440             my $sub = $1 ;
441             return (&$sub(@_))[0] if defined &$sub ;
442             }
443             elsif ($type eq 'ref') {
444             my $val = $_[0] ;
445             return $val if ref($val) ;
446             }
447             elsif ($type eq 'array') {
448             my @val = @_ ;
449             return \@val ;
450             }
451             elsif ($type eq 'hash') {
452             my %val = @_ ;
453             return \%val ;
454             }
455             elsif ($type eq 'refarray') {
456             my $val = $_[0] ;
457             return $val if ref($val) eq 'ARRAY' ;
458             }
459             elsif ($type eq 'refhash') {
460             my $val = $_[0] ;
461             return $val if ref($val) eq 'HASH' ;
462             }
463             elsif ($type =~ /^array(&?[\w:]+)/ ) {
464             my $tp = $1 ;
465             my @val = @_ ;
466             my $accept_undef = $tp =~ /^(?:any|string|boolean|integer|floating|sub_\w+|&\w+)$/ ? 1 : undef ;
467             if ( $accept_undef ) {
468             return [map { CLASS_HPLOO_ATTR_TYPE($class , $tp , $_) } @val] ;
469             }
470             else {
471             return [map { CLASS_HPLOO_ATTR_TYPE($class , $tp , $_) || () } @val] ;
472             }
473             }
474             elsif ($type =~ /^hash(&?[\w:]+)/ ) {
475             my $tp = $1 ;
476             my %val = @_ ;
477             foreach my $Key ( keys %val ) {
478             $val{$Key} = CLASS_HPLOO_ATTR_TYPE($class , $tp , $val{$Key}) ;
479             }
480             return \%val ;
481             }
482             elsif ($type =~ /^refarray(&?[\w:]+)/ ) {
483             my $tp = $1 ;
484             return undef if ref($_[0]) ne 'ARRAY' ;
485             my $ref = CLASS_HPLOO_ATTR_TYPE($class , "array$tp" , @{$_[0]}) ;
486             @{$_[0]} = @{$ref} ;
487             return $_[0] ;
488             }
489             elsif ($type =~ /^refhash(&?[\w:]+)/ ) {
490             my $tp = $1 ;
491             return undef if ref($_[0]) ne 'HASH' ;
492             my $ref = CLASS_HPLOO_ATTR_TYPE($class , "hash$tp" , %{$_[0]}) ;
493             %{$_[0]} = %{$ref} ;
494             return $_[0] ;
495             }
496             elsif ($type =~ /^\w+(?:::\w+)*$/ ) {
497             return( UNIVERSAL::isa($_[0] , $type) ? $_[0] : undef ) ;
498             }
499             return undef ;
500             }
501             ` ;
502            
503             $USE_BASE_REF = "use Class::HPLOO::Base ;" ;
504            
505             $CLASS_NEW =~ s/[ \t]*\n[ \t]*/ /gs ;
506             $CLASS_NEW_ATTR =~ s/[ \t]*\n[ \t]*/ /gs ;
507             $SUB_AUTO_OO =~ s/[ \t]*\n[ \t]*/ /gs ;
508             $SUB_ALL_OO =~ s/[ \t]*\n[ \t]*/ /gs ;
509             $SUB_HTML_EVAL =~ s/[ \t]*\n[ \t]*/ /gs ;
510             $SUB_ATTR =~ s/[ \t]*\n[ \t]*/ /gs ;
511            
512             $LOADED = 1 ;
513            
514             }
515            
516             ##########
517             # IMPORT #
518             ##########
519            
520             my %BUILDING ;
521            
522             sub import {
523             my $class = shift ;
524            
525             ($SUB_OO , $DUMP , $ALL_OO , $NICE , $NO_CLEAN_ARGS , $ADD_HTML_EVAL , $DO_NOTHING , $BUILD , $BUILD_PM_FILE , $BUILD_PM_VERSION , $USE_BASE , $RET_CACHE , $FIRST_SUB_IDENT , $PREV_CLASS_NAME) = () ;
526            
527             my $args = join(" ", @_) ;
528            
529             if ( $args =~ /(?:use)?[_\s]*base/i) { $USE_BASE = 1 ;}
530            
531             if ( $args =~ /build/i) { $args =~ s/(?:build|dump|nice)//gsi ; $BUILD = 1 ; $NICE = 1 ;}
532             elsif ( $args =~ /nice/i) { $args = "dump alloo nocleanarg" ; $NICE = 1 ;}
533            
534             if ( $args =~ /all[_\s]*oo/i) { $SUB_OO = $SUB_ALL_OO ; $ALL_OO = 1 ;}
535             else { $SUB_OO = $SUB_AUTO_OO ;}
536            
537             if ( $args =~ /dump/i) { $DUMP = 1 ;}
538            
539             if ( $args =~ /no[_\s]*clean[_\s]*arg/i) { $NO_CLEAN_ARGS = 1 ;}
540            
541             if ( $args =~ /do\s*nothing/i ) { $DO_NOTHING = 1 ;}
542            
543             if ( $BUILD ) {
544             unshift (@INC, sub {
545             my @call = caller ;
546            
547             if ( $BUILDING{ $call[1] } ) {
548             my $fh ;
549             open ($fh, $BUILD_PM_FILE ) ;
550             return $fh ;
551             }
552            
553             undef ;
554             }) if !%BUILDING ;
555            
556             my @call = caller ;
557             $BUILDING{ $call[1] } = 1 ;
558             }
559            
560             }
561            
562             ##########
563             # FILTER #
564             ##########
565            
566             FILTER_ONLY( all => \&filter_html_blocks , code => \&CLASS_HPLOO , all => \&dump_code ) ;
567            
568             #############
569             # DUMP_CODE #
570             #############
571            
572             sub dump_code {
573 5 50   5 0 727 return if $DO_NOTHING ;
574            
575 5 50       12 $_ = $CACHE{$_} if $RET_CACHE ;
576            
577 5         20 $_ =~ s/_CLASS_HPLOO_FIXER_//gs ;
578 5         19 $_ =~ s/_CLASS_HPLOO_\/DIV_FIX_//gs ;
579 5         18 $_ =~ s/_CLASS_HPLOO_DIV_FIX/\//gs ;
580            
581             #if ( $DUMP || $BUILD ) {
582 5 50       16 $_ =~ s/#_CLASS_HPLOO_CMT_(\d+)#/$COMMENTS{$1}/gs if %COMMENTS ;
583             #}
584            
585 5         10 %COMMENTS = () ;
586            
587 5 50       18 if ( $DUMP ) {
588 0         0 my $syntax = $_ ;
589 0         0 $syntax =~ s/\r\n?/\n/gs ;
590 0         0 print "$syntax\n" ;
591 0         0 exit ;
592             }
593            
594 5 50       16 if ( $BUILD ) {
595 0         0 $BUILD = $_ ;
596             }
597            
598 5         29 $CACHE{$CACHE{_}} = $_ ;
599 5         9 ++$CACHE{X} ;
600            
601 5         11 $RET_CACHE = $CACHE{_} = undef ;
602            
603 5         17 %CLASSES = %HTML = () ;
604            
605             }
606            
607             ######################
608             # FILTER_HTML_BLOCKS #
609             ######################
610            
611             sub filter_html_blocks {
612 5 50 33 5 0 1558 return if $DO_NOTHING || $_ !~ /\S/s ;
613            
614 5 50       19 if ( $CACHE{X} == 50 ) { %CACHE = () ;}
  0         0  
615            
616 5 50       24 if ( $CACHE{$_} ) { $RET_CACHE = 1 ; return ;}
  0         0  
  0         0  
617            
618 5         8 my $line_init ;
619             {
620 5         10 my ($c,@call) ;
  5         6  
621 5   100     47 while( ($call[0] =~ /^Filter::/ || $call[0] eq '') && $c <= 10 ) { @call = caller(++$c) ;}
  20   66     236  
622 5         13 $line_init = $call[2] ;
623             }
624            
625 5         189 $_ =~ s/(?:\r\n?|\n)/\n/gs ;
626            
627 5 50       18 if ( $_ =~ /(.*)\n__END__\n.*?$/s ) {
628 0         0 $_ = $1 ;
629             }
630            
631 5         529 %CLASSES = %HTML = %COMMENTS = () ;
632            
633 5 50       25 my $set_init_line = !$BUILD ? "\n#line $line_init\n" : undef ;
634 5         24 my $data = $CACHE{_} = $set_init_line . clean_comments("\n".$_) ;
635            
636 5         17 for(1..2) {
637 10         75 $data =~ s/(\{\s*)((?:q|qq|qr|qw|qx|tr|x|y|s|m)\s*\})/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## {s}
638 10         23 $data =~ s/(\W)((?:q|qq|qr|qw|qx|tr|x|y|s|m)\s*=>)/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## s =>
639 10         34 $data =~ s/(->)((?:q|qq|qr|qw|qx|tr|x|y|s|m)\W)/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## ->s
640            
641 10         98 $data =~ s/([\$\@\%\*])((?:q|qq|qr|qw|qx|tr|x|y|s|m)(?:\W|\s+\S))/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## $q
642 10         43 $data =~ s/(-[sx])(\s+\S|[^\w\s])/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## -s foo
643 10         42 $data =~ s/(\Wsub\s+)((?:q|qq|qr|qw|qx|tr|x|y|s|m)[\s\(\{])/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## sub m {}
644            
645 10         284 $data =~ s/(\W)((?:q|qq|qr|qw|qx|tr|x|y|s|m)\s*[=,\)\}\]\>\*\;\+\-])/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## txt y = | (x-y) | , y ; | (y+1)
646            
647 10         28 $data =~ s/(<)(<)/$1\_CLASS_HPLOO_FIXER_$2/gs ; ## $x <<= 1 ;
648             }
649            
650 5         14 $data = _fix_div($data) ;
651            
652 5         35 $data =~ s/<%[ \t]*html?(\w+)[ \t]*>(?:(\(.*?\))|)/CLASS_HPLOO_HTML('$1',$2)/sgi ;
653            
654 5 50 33     27 if ( !$BUILD && !$NICE ) {
655 5         28 $data =~ s/([\r\n][ \t]*<%\s*html\w+[ \t]*(?:\(.*?\))?[ \t]*[^\r\n]*(?:\r\n|[\r\n]).*?(?:\r\n|[\r\n])?%>)((?:\r\n|[\r\n])?)/
656 2         7 my $blk = $1 ;
657 2         8 my $dt = substr($data , 0 , pos($data)) . $blk . $2 ;
658 2         10 my $ln = ($dt =~ tr~\n~~s) + $line_init ;
659 2         16 "$blk#line $ln\n";
660             /egsix ;
661             }
662            
663 5         27 $data =~ s/([\r\n])[ \t]*<%\s*html(\w+)[ \t]*(\(.*?\))?[ \t]*[^\r\n]*(?:\r\n|[\r\n])(.*?)(?:\r\n|[\r\n])?%>(?:\r\n|[\r\n])?/
664 2         7 my $tag = "" ;
665 2 100       12 $HTML{$tag}{a} = $3 if $3 ne '' ;
666 2         9 $HTML{$tag}{1} = "$1\$CLASS_HPLOO{HTML}{'$2'} = " ;
667 2         5 $HTML{$tag}{2} = "<<'CLASS_HPLOO_HTML';" ;
668 2         8 $HTML{$tag}{3} = "\n$4" ;
669 2         7 $HTML{$tag}{4} = "\nCLASS_HPLOO_HTML\n" ;
670 2         16 $tag ;
671             /egsix ;
672            
673 5         14 $data =~ s/([\r\n])<%.*?%>/$1/gs ;
674            
675 5 100       17 $ADD_HTML_EVAL = 1 if %HTML ;
676            
677 5         17 foreach my $Key ( keys %HTML ) {
678 2 100       8 if ( $HTML{$Key}{a} ne '' ) {
679 1         5 my $args = &generate_args_code( delete $HTML{$Key}{a} ) ;
680 1         5 $HTML{$Key}{2} =~ s/;$// ;
681 1         7 $HTML{$Key}{2} = "[ q`$args` , $HTML{$Key}{2} ];" ;
682             }
683             }
684            
685 5         21 $_ = $SYNTAX = $data ;
686             }
687            
688             ############
689             # _FIX_DIV #
690             ############
691            
692             sub _fix_div {
693 5     5   10 my ( $data ) = @_ ;
694            
695 5         7 my ($data_ok , $init , $p) ;
696            
697 5         19 my $re = qr/
698             (?:
699             [^\/\\]?\/
700             |
701             (?:\\\\|\\\/)\/
702             |
703             (?:
704             (?:\\\/)
705             |
706             [^\/]
707             )+
708             (?!\\)
709             [^\/]?\/
710             )
711             /sx ;
712            
713 5         15 $data =~ s/\r\n?/\n/gs ;
714            
715 5         26 while( $data =~ /(.*?)\/(.*)/gs ) {
716 1         3 $init = $1 ;
717 1         3 $data = $2 ;
718            
719 1         3 $p = pos($data) ;
720            
721 1 50 0     34 if ( $init =~ /(?:^|\W)(?:tr|s|y)\s*$/s ) {
    0          
    0          
722 1         120 my ($patern,$rest) = ( $data =~ /^($re$re)(.*)/s ) ;
723 1         6 $data_ok .= "$init/$patern" ;
724 1         5 $data = $rest ;
725             }
726             elsif ( $init =~ /(?:^|\W)(?:q|qq|qr|qw|qx|m)\s*$/s || $init =~ /(?:[=!]~|\()\s*$/s ) {
727 0         0 my ($patern,$rest) = ( $data =~ /^($re)(.*)/s ) ;
728 0         0 $data_ok .= "$init/$patern" ;
729 0         0 $data = $rest ;
730             }
731             elsif ( $data =~ /^=/s ) {
732 0         0 $data_ok .= "$init\_CLASS_HPLOO_DIV_FIX" ;
733             }
734             else {
735 0         0 $data_ok .= "$init\_CLASS_HPLOO_\/DIV_FIX_/" ;
736             }
737             }
738            
739 5         18 $data_ok .= substr($data , $p) ;
740            
741 5         17 return $data_ok ;
742             }
743            
744             ###############
745             # CLASS_HPLOO #
746             ###############
747            
748             sub CLASS_HPLOO {
749 5 50 33 5 0 183045 return if $DO_NOTHING || $RET_CACHE || $_ !~ /\S/s ;
      33        
750            
751 5         15 my $data = $_ ;
752            
753 5         74 my (@ph) = ( $data =~ /(\Q$;\E....\Q$;\E)/gs );
754 5         12 my $phx = -1 ;
755 5         42 $data =~ s/\Q$;\E....\Q$;\E/"$;HPL_PH". ++$phx ."$;"/egs ;
  13         55  
756            
757 5         24 my $syntax = parse_class($data) ;
758            
759 5 50       20 if ( %CLASSES ) {
760 0         0 1 while( $syntax =~ s/#_CLASS_HPLOO_CLASS_(\d+)#/$CLASSES{$1}/gs ) ;
761             }
762            
763 5 100       1363 $syntax .= "\n1;\n" if $syntax !~ /\s*1\s*;\s*$/ ;
764            
765 5         41 $syntax =~ s/(<\?CLASS_HPLOO_HTML_\w+\?>)/$HTML{$1}{1}$HTML{$1}{2}$HTML{$1}{3}$HTML{$1}{4}/gs ;
766 5         111 $syntax =~ s/\Q$;\EHPL_PH(\d+)\Q$;\E/$ph[$1]/gs ;
767            
768 5         16 %HTML = () ;
769            
770 5         35 $_ = $SYNTAX = $syntax ;
771             }
772            
773             ###############
774             # PARSE_CLASS #
775             ###############
776            
777             sub parse_class {
778 12     12 0 25 my $data = shift ;
779 12         16 my $is_subclass = shift ;
780            
781 12         18 my $first_sub_ident = $FIRST_SUB_IDENT ;
782 12         15 $FIRST_SUB_IDENT = undef ;
783            
784 12         13 my $syntax ;
785 12         15 my ( $init , $class ) ;
786            
787 12         84 while( $data =~ /^
788             (.*?\W|)
789             (
790             [cC]lass\s+
791             [\w\.:]+
792             (?:
793             \s*\[[ \t\w\.-]+\]
794             )?
795             (?:
796             \s+[eE]xtends\s*[^\{\}]*
797             )?
798             )
799             \s*(\{.*)
800             $/gsx ) {
801 7         20 $init = $1 ;
802 7         18 $class = $2 ;
803 7         22 $data = $3 ;
804            
805 7         22 my @ret = extract_block($data) ;
806            
807 7 50       20 if ($ret[0] ne '') {
808 7         12 $class .= $ret[0] ;
809 7         14 $data = $ret[1] ;
810 7         18 $init =~ s/[ \t]+$//s ;
811            
812 7         21 $class = build_class($class) ;
813            
814 7 50       17 if ( $is_subclass ) {
815 0         0 $CLASSES{ ++$CLASSES{x} } = $class ;
816 0         0 $class = "#_CLASS_HPLOO_CLASS_$CLASSES{x}#" ;
817             }
818             }
819            
820 7         94 $syntax .= $init . $class ;
821             }
822            
823 12         18 $syntax .= $data ;
824            
825 12         18 $FIRST_SUB_IDENT = $first_sub_ident ;
826            
827 12         40 return( $syntax ) ;
828             }
829            
830             #################
831             # EXTRACT_BLOCK #
832             #################
833            
834             sub extract_block {
835 22     22 0 32 my ( $data ) = @_ ;
836            
837 22         23 my $block ;
838            
839             my $level ;
840 22         92 while( $data =~ /(.*?)([\{\}])/gs ) {
841 142         287 $block .= $1 . $2 ;
842 142 100       342 if ($2 eq '{') { ++$level ;}
  71 50       91  
843 71         79 elsif ($2 eq '}') { --$level ;}
844 142 100       633 if ($level <= 0) { last ;}
  22         30  
845             }
846            
847 22 50       48 if ( $level != 0 ) {
848 0 0       0 die("Missing right curly or square bracket at data:\n$_[0]") if !$DUMP ;
849             }
850            
851 22         75 my ($end) = ( $data =~ /\G(.*)$/s ) ;
852            
853 22         77 return ($block,$end) ;
854             }
855            
856             ##################
857             # CLEAN_COMMENTS #
858             ##################
859            
860             sub clean_comments {
861 5     5 0 9 my $data = shift ;
862            
863 5         7 if ( 1 || $DUMP || $BUILD ) {
864 5 0       463 $data =~ s/(?:([\r\n][ \t]*)(#+[^\r\n]*)|([^\r\n\#\$])(#+[^\r\n]*))/++$COMMENTS{i} ; $COMMENTS{ $COMMENTS{i} } = (defined $2 ? $2 : $4) ; (defined $1 ? $1 : $3) . "#_CLASS_HPLOO_CMT_$COMMENTS{i}#"/gse ;
  0 0       0  
  0         0  
  0         0  
865             }
866             else {
867             $data =~ s/(?:([\r\n][ \t]*)(#+[^\r\n]*)|([^\r\n\#\$])(#+[^\r\n]*))/ my $s = ' ' x length(defined $2 ? $2 : $4) ; (defined $1 ? $1 : $3) . "$s" /gse ;
868             }
869            
870 5         20 return $data ;
871             }
872            
873             ###############
874             # BUILD_CLASS #
875             ###############
876            
877             sub build_class {
878 7     7 0 19 my $code = shift ;
879            
880 7         56 my ($name,$version,$extends,$body) = ( $code =~ /
881             class\s+
882             ([\w\.:]+)
883             (?:
884             \s*\[[ \t]*([ \t\w\.-]+?)[ \t]*\]
885             |)
886             (?:
887             \s+extends\s+
888             (
889             [\w\.:]+
890             (?:
891             \s*,\s*[\w\.:]+
892             )*
893             )
894             \s*
895             |
896             \s+extends
897             |)
898             \s*{(.*)
899             $/six ) ;
900            
901 7         18 $version =~ s/["'\s]//gs ;
902            
903 7         44 $body =~ s/}\s*$//s ;
904            
905 7         18 $name =~ s/^\./$PREV_CLASS_NAME\::/gs ;
906            
907 7         22 $name = package_name($name);
908            
909 7         29 my @extends = split(/\s*,\s*/s , $extends) ;
910 7         18 foreach my $extends_i ( @extends ) {
911 4         10 $extends_i = package_name($extends_i);
912             }
913            
914 7         13 my $isa_base = 'Class::HPLOO::Base UNIVERSAL' ;
915            
916 7 100       21 if ( @extends ) {
917 3         14 $extends = "push(\@ISA , qw(". join(' ',@extends) ." $isa_base)) ;" ;
918             }
919             else {
920 4         13 $extends = "\@ISA = qw($isa_base) ;" ;
921             }
922            
923 7         11 my $version_number ;
924 7 50       23 if ( $version ) {
925 0         0 $version_number = $version ;
926 0         0 $version = "\$VERSION = '$version' ;" ;
927             }
928            
929 7         28 my ($name_end) = ( $name =~ /(\w+)$/ );
930            
931             ## vars () ;
932 7         29 $body =~ s~
933             ((?:^|[^\w\s])\s*)(?:use\s+)?vars\s*\(
934             (
935             (?:
936             \s*[\$\@\%]\w[\w:]*\s*
937             (?:,\s*[\$\@\%]\w[\w:]*\s*)*
938             )
939             )
940             \s*,?\s*
941             \)
942             ~
943 2         8 my @vars = split(/\s*,\s*/s , $2) ;
944 2         14 "$1use vars qw(". join(" ", @vars) .")" ;
945             ~gsex ;
946            
947             ## attr ( foo , int bar , Foo::Bar bar ) ;
948 7         10 my $add_attr ;
949            
950             {
951 7         11 my $vars = qr/(?:(?:\w+\s+)*?&?\w+\s+|(?:\w+\s+)*?\w+(?:(?:::|\.)\w+)*\s+)?\w+/s ;
  7         40  
952            
953 7         759 $body =~ s~
954             ((?:^|[^\w\s])\s*)(?:attrs?|attributes?)\s*\(
955             (
956             (?:
957             \s*$vars\s*
958             (?:,\s*$vars\s*)*
959             )
960             )
961             \s*,?\s*
962             \)
963             ~
964 1         3 $add_attr = 1 ;
965 1         29 "${1}CLASS_HPLOO_ATTR('$2')"
966             ~gsex ;
967             }
968            
969 7 100       40 my $new = $add_attr ? $CLASS_NEW_ATTR : $CLASS_NEW ;
970 7         95 $new =~ s/%CLASS%/$name_end/gs ;
971 7         75 $new =~ s/%PACKAGE%/$name/gs ;
972            
973             ##################
974            
975             {
976 7         8 my $prev_class_name = $PREV_CLASS_NAME ;
  7         9  
977 7         11 $PREV_CLASS_NAME = $name ;
978            
979 7         18 $body = parse_class($body , 1) ;
980            
981 7         15 $PREV_CLASS_NAME = $prev_class_name ;
982             }
983            
984 7         19 my ($body , $extra_vars) = parse_subs($body,$name,$version_number) ;
985            
986 7         36 $body =~ s/^[ \t]*\n//gs ;
987            
988 7 100       27 my $sub_attr = $add_attr ? $SUB_ATTR : undef ;
989 7         32 $sub_attr =~ s/%PACKAGE%/$name/gs ;
990            
991 7 100       18 my $sub_html_eval = $ADD_HTML_EVAL ? $SUB_HTML_EVAL : undef ;
992            
993             ###################
994            
995 7         7 my @local_vars ;
996            
997 7 100       21 push(@local_vars , '$this') if !$ALL_OO ;
998            
999 7 50 33     40 push(@local_vars , @$extra_vars) if ref $extra_vars && @$extra_vars ;
1000            
1001 7         10 my $local_vars ;
1002 7 100       15 if ( @local_vars ) { $local_vars = "my (". join(' , ', @local_vars) .") ;" ;}
  6         18  
1003            
1004             ###################
1005            
1006 7         15 my @global_vars = qw(%CLASS_HPLOO @ISA) ;
1007            
1008 7 50       16 push(@global_vars , '$VERSION') if $version ;
1009            
1010 7         8 my $global_vars ;
1011 7 50       16 if ( @global_vars ) { $global_vars = "use vars qw(". join(' ', @global_vars) .") ;" ;}
  7         21  
1012            
1013             ###################
1014            
1015 7         19 my $const_class = "my \$CLASS = '$name' ; sub __CLASS__ { '$name' } ;" ;
1016            
1017 7 100       17 my $use_base_ref = $USE_BASE ? $USE_BASE_REF : '' ;
1018            
1019 7         7 my $class ;
1020            
1021 7 50 33     30 if ( $NICE || $BUILD ) {
1022 0         0 $new = format_nice_sub($new) ;
1023 0 0       0 $sub_html_eval = format_nice_sub($sub_html_eval) if $sub_html_eval ;
1024 0 0       0 $sub_attr = format_nice_sub($sub_attr) if $sub_attr ;
1025            
1026 0         0 $class .= "{ package $name ;\n" ;
1027 0         0 $class .= "\n${FIRST_SUB_IDENT}use strict qw(vars) ; no warnings ;\n" ;
1028            
1029 0 0       0 $class .= "\n$FIRST_SUB_IDENT$global_vars\n" if $global_vars ;
1030            
1031 0 0       0 if ( $version ) {
1032 0         0 $version =~ s/;\s+/;\n$FIRST_SUB_IDENT/ ;
1033 0         0 $class .= "\n${FIRST_SUB_IDENT}$version\n" ;
1034             }
1035            
1036 0 0       0 $class .= "\n$FIRST_SUB_IDENT$extends\n" if $extends ;
1037            
1038 0 0       0 $class .= "\n$FIRST_SUB_IDENT$local_vars\n" if $local_vars ;
1039            
1040 0         0 $class .= "\n$FIRST_SUB_IDENT$const_class\n" ;
1041            
1042 0 0       0 $class .= "$new\n" if !$USE_BASE ;
1043            
1044 0 0       0 $class .= "\n$sub_html_eval\n" if $sub_html_eval ;
1045            
1046 0 0 0     0 $class .= "\n$sub_attr\n" if !$USE_BASE && $sub_attr ;
1047            
1048 0 0       0 $class .= "\n$FIRST_SUB_IDENT$use_base_ref\n" if $use_base_ref ;
1049             }
1050             else {
1051 7 100       15 $new = '' if $USE_BASE ;
1052 7 100       18 $sub_attr = '' if $USE_BASE ;
1053            
1054 7         70 $class .= "{ package $name ; use strict qw(vars) ; no warnings ;$global_vars$version$extends$local_vars$const_class$new$sub_html_eval$sub_attr$use_base_ref\n" ;
1055 7         29 $body =~ s/^(?:\r\n?|\n)//s ;
1056             }
1057            
1058 7         12 $class .= $body ;
1059            
1060 7         10 $class .= "\n}\n" ;
1061            
1062 7         51 return( $class ) ;
1063             }
1064            
1065             ###################
1066             # FORMAT_NICE_SUB #
1067             ###################
1068            
1069             sub format_nice_sub {
1070 0     0 0 0 my $sub = shift ;
1071 0 0       0 if ( !$sub ) { return $sub ;}
  0         0  
1072 0         0 $sub =~ s/({\s+)/$1\n$FIRST_SUB_IDENT /s ;
1073 0         0 $sub =~ s/(\s*;)\s*/$1\n$FIRST_SUB_IDENT /gs ;
1074 0         0 $sub =~ s/^(\s*)/$1\n$FIRST_SUB_IDENT/gs ;
1075 0         0 $sub =~ s/\s+$//gs ;
1076 0         0 $sub =~ s/\n[ \t]*(})$/\n$FIRST_SUB_IDENT$1/s ;
1077 0         0 $sub =~ s/(\S)( {) (\S)/$1$2\n$FIRST_SUB_IDENT $3/gs ;
1078 0         0 return $sub ;
1079             }
1080            
1081             ###############
1082             # FORMAT_NICE #
1083             ###############
1084            
1085             sub format_nice {
1086 0     0 0 0 my $code = shift ;
1087 0 0       0 if ( !$code ) { return $code ;}
  0         0  
1088 0         0 $code =~ s/(\s*;)\s*/$1\n$FIRST_SUB_IDENT/gs ;
1089 0         0 $code =~ s/^(\s*)/$1\n$FIRST_SUB_IDENT/gs ;
1090 0         0 return $code ;
1091             }
1092            
1093             ##############
1094             # PARSE_SUBS #
1095             ##############
1096            
1097             sub parse_subs {
1098 7     7 0 15 my $data = shift ;
1099 7         9 my $class_name = shift ;
1100 7         9 my $class_version = shift ;
1101            
1102 7   50     34 $class_version ||= '0.01' ;
1103            
1104 7         5 my $syntax ;
1105            
1106 7         10 my ( $init , $sub , %inline ) ;
1107            
1108 7         21 $data =~ s/\n__\[(\w+)\]__[ \t]*\n(.*?)\n__\[\1\]__[ \t]*\n/\nsub[$1] __INLINE_CODE__ {\n$2\n}\n/gs ;
1109            
1110 7         98 while( $data =~ /^
1111             (.*?\W|)
1112             (
1113             (?:
1114             (?:static)
1115             \s+
1116             )?
1117             sub\s+[\w\.:]+\s*
1118             (?:\(.*?\)|)?
1119             |
1120             sub\[\w+\].*?
1121             )
1122             \s*
1123             (\{.*)
1124            
1125             $/gsx ) {
1126 15         28 $init = $1 ;
1127 15         25 $sub = $2 ;
1128 15         30 $data = $3 ;
1129            
1130 15 100       31 if ( !$FIRST_SUB_IDENT ) {
1131 5         7 $FIRST_SUB_IDENT = $init ;
1132 5         51 $FIRST_SUB_IDENT =~ s/.*?([ \t]*)$/$1/s ;
1133             }
1134            
1135 15         29 my @ret = extract_block($data) ;
1136            
1137 15 50       43 if ($ret[0] ne '') {
1138 15         22 $sub .= $ret[0] ;
1139 15         18 $data = $ret[1] ;
1140 15         66 $sub = build_sub($sub,\%inline) ;
1141             }
1142 15         107 $syntax .= $init . $sub ;
1143             }
1144            
1145 7         11 $syntax .= $data ;
1146            
1147 7         7 my @extra_vars ;
1148            
1149 7         31 foreach my $Key ( sort keys %inline ) {
1150             #my $src = "use Inline $Key => <<'__INLINE_$Key\_SRC__' , NAME => '$class_name' , VERSION => '$class_version' ;\n\n" ;
1151            
1152 0         0 push(@extra_vars , "\%__${Key}__") ;
1153            
1154 0         0 my $src_header ;
1155 0         0 eval("require Class::HPLOO::Inline$Key") ;
1156 0 0       0 if (!$@) {
1157 0         0 $src_header = eval("Class::HPLOO::Inline$Key\::code_header()") ;
1158             }
1159            
1160 0         0 my $src = q`
1161             my $INLINE_INSTALL ;
1162             BEGIN {
1163             use Config ;
1164             my @installs = ($Config{installarchlib} , $Config{installprivlib} , $Config{installsitelib}) ;
1165             foreach my $i ( @installs ) { $i =~ s/[\\\\\/]/\//gs ;}
1166             $INLINE_INSTALL = 1 if ( __FILE__ =~ /\.pm$/ && ( join(" ",@INC) =~ /\Wblib\W/s || __FILE__ =~ /^(?:\Q$installs[0]\E|\Q$installs[1]\E|\Q$installs[2]\E)/ ) ) ;
1167            
1168             ` . qq`
1169            
1170             my \$config = 'use Inline $Key => Config' ;
1171             foreach my \$k (sort keys \%__${Key}__ ) {
1172             \$config .= " => '\$k' => \\\$__${Key}__{'\$k'}" ;
1173             }
1174             eval(\$config) ;
1175             }
1176             `;
1177            
1178 0         0 $src =~ s/^\s+//s ;
1179 0         0 $src =~ s/\s+$//s ;
1180 0         0 $src =~ s/\s+/ /gs ;
1181 0         0 $src .= "\n\n" ;
1182            
1183 0   0     0 my $pm_ver = $BUILD_PM_VERSION || $class_version ;
1184            
1185 0         0 $src .= qq`use Inline $Key => <<'__INLINE_$Key\_SRC__' , ( \$INLINE_INSTALL ? (NAME => '$class_name' , VERSION => '$pm_ver' ) : () ) ;\n\n` ;
1186            
1187 0         0 $src .= $src_header ;
1188 0         0 $src .= $inline{$Key} ;
1189 0         0 $src =~ s/\s+$/\n/s ;
1190 0         0 $src .= "\n__INLINE_$Key\_SRC__\n\n" ;
1191 0         0 $syntax .= $src ;
1192             }
1193            
1194 7         35 return($syntax , \@extra_vars) ;
1195             }
1196            
1197             #############
1198             # BUILD_SUB #
1199             #############
1200            
1201             sub build_sub {
1202 15     15 0 23 my $code = shift ;
1203 15         18 my $inline = shift ;
1204 15         14 my $sub ;
1205            
1206 15         24 $code =~ s/\r\n?/\n/gs ;
1207            
1208 15 50       36 if ( $code =~ /^\s*sub\[\w+\]/ ) {
1209 0         0 my ($language,$header,$body) = ( $code =~ /^\s*sub\[(\w+)\]\s*(.*?)\s*{(.*)/s );
1210 0         0 $language = uc($language) ;
1211            
1212 0 0       0 if ( $header eq '__INLINE_CODE__' ) {
1213 0         0 $body =~ s/[ \t]*}\s*$/\n/s ;
1214 0         0 $$inline{$language} .= $body ;
1215             }
1216             else {
1217 0 0       0 if ( $language eq 'C' ) {
1218 0         0 require Class::HPLOO::InlineC ;
1219 0         0 $body = Class::HPLOO::InlineC::apply_CPL($body) ;
1220             }
1221 0         0 my $src = "$header {$body" ;
1222 0         0 $src =~ s/[ \t]*}\s*$/}\n\n/s ;
1223 0         0 $$inline{$language} .= $src ;
1224             }
1225             }
1226             else {
1227 15         103 my ($sub_type,$name,$prototype,$body) = ( $code =~ /^\s*(?:(static)\s+)?sub\s+([\w\.:]+)\s*((?:\(.*?\))?)\s*{(.*)/s );
1228 15         61 $body =~ s/}\s*$//s ;
1229            
1230 15         30 $name = package_name($name);
1231            
1232 15 50       37 my $no_sub_oo = $sub_type eq 'static' ? 1 : undef ;
1233            
1234 15         11 my $my_args ;
1235 15 100       29 if ( $prototype ) {
1236 5 50       20 if ( $prototype =~ /^\(\s*\*\s*\)$/ ) {
1237 0         0 $no_sub_oo = 1 ;
1238 0         0 $prototype = '' ;
1239             }
1240             else {
1241 5         14 $my_args = &generate_args_code($prototype) ;
1242 5 50       9 if ( $my_args ) { $prototype = '' ;}
  5 0       10  
1243 0         0 elsif (!$no_sub_oo) { $prototype =~ s/^(\()(.*)$/$1\$$2/gs ;}
1244             }
1245             }
1246            
1247 15 50       42 my $my_code = (!$no_sub_oo ? $SUB_OO : '') . $my_args ;
1248            
1249 15 50 33     64 if ( $NICE || $BUILD ) {
1250 0         0 my ($n,$ident) = ( $body =~ /(\r\n?|\n)([ \t]+)/s );
1251 0         0 $my_code =~ s/(\s*;)\s*/$1$n$ident/gs ;
1252 0         0 $my_code =~ s/^(\s*)/$1$n$ident/gs ;
1253             }
1254            
1255 15         46 $sub = "sub $name$prototype {$my_code$body}" ;
1256             }
1257            
1258 15         36 return $sub ;
1259             }
1260            
1261             ################
1262             # PACKAGE_NAME #
1263             ################
1264            
1265             sub package_name {
1266 26     26 0 34 my ( $pack ) = @_ ;
1267            
1268 26         44 $pack =~ s/[:\.]+/::/gs ;
1269 26         37 $pack =~ s/:+$//s ;
1270            
1271 26         58 return( $pack ) ;
1272             }
1273            
1274             ######################
1275             # GENERATE_ARGS_CODE #
1276             ######################
1277            
1278             sub generate_args_code {
1279 6     6 0 34 my $args = shift ;
1280            
1281 6         8 my $my_args ;
1282            
1283 6 50       38 if ($args =~ /\(
1284             \s*
1285             (
1286             (?:[\$\@\%]|\\[\@\%])\w[\w:]*\s*
1287             (?:,\s*(?:[\$\@\%]|\\[\@\%])\w[\w:]*\s*)*
1288             )
1289             \s*,?\s*
1290             \)/sx) {
1291 6         17 my ($vars , $clean_args) = $1 ;
1292 6         70 $vars =~ s/^\s+//gs ;
1293 6         19 $vars =~ s/\s+$//gs ;
1294 6         26 my @vars = split(/\s*,\s*/s , $vars) ;
1295            
1296 6         14 foreach my $vars_i ( @vars ) {
1297 10         57 my ($ref,$type,$var) = ( $vars_i =~ /(\\?)([\$\@\%])(.*?)\s*$/gs );
1298            
1299 10 50       25 if ( $clean_args ) { $my_args .= "my $vars_i ;" ; next ;}
  0         0  
  0         0  
1300            
1301 10 100       27 if ($ref) {
    100          
1302 4         9 my $ref_type = $REF_TYPES{$type} ;
1303            
1304 4 100       15 if ($ref_type eq 'ARRAY') {
    50          
1305 2         7 $my_args .= "my $type$var = ref(\$_[0]) eq 'ARRAY' ? \@\{ shift(\@_) } : ( ref(\$_[0]) eq 'HASH' ? \%\{ shift(\@_) } : shift(\@_) ) ;" ;
1306             }
1307             elsif ($ref_type eq 'HASH') {
1308 2         8 $my_args .= "my $type$var = ref(\$_[0]) eq 'HASH' ? \%\{ shift(\@_) } : ( ref(\$_[0]) eq 'ARRAY' ? \@\{ shift(\@_) } : shift(\@_) ) ;" ;
1309             }
1310             else {
1311 0         0 $my_args .= "my $type$var = ref(\$_[0]) eq '$ref_type' ? $type\{ shift(\@_) } : shift(\@_) ;" ;
1312             }
1313             }
1314 1         4 elsif ($type ne '$') { $my_args .= "my $vars_i = \@_ ;" ; $clean_args = 1 ;}
  1         4  
1315 5         18 else { $my_args .= "my $vars_i = shift(\@_) ;" ;}
1316             }
1317 6 100       19 if ($clean_args) { $my_args .= "\@_ = () ;" ;}
  1         3  
1318             }
1319            
1320 6         17 return $my_args ;
1321             }
1322            
1323             ###############
1324             # BUILD_HPLOO #
1325             ###############
1326            
1327             sub build_hploo {
1328 0     0 0   my ( $hploo_file , $pm_file , $pm_version ) = @_ ;
1329            
1330 0           my $file_data ;
1331             {
1332 0           open (my $fh,$hploo_file) ;
  0            
1333 0           $file_data = join '' , <$fh> ;
1334 0           close ($fh) ;
1335             }
1336            
1337 0           my ($file_init,$file_splitter,$file_end) ;
1338            
1339 0 0         if ( $file_data =~ /(.*)(\n__END__\n)(.*?)$/s ) {
1340 0           ($file_init,$file_splitter,$file_end) = ($1 , $2 , $3) ;
1341             }
1342             else {
1343 0           $file_init = $file_data ;
1344             }
1345            
1346 0           my ($import_args) = ( $file_init =~ /(?:^|\n)[ \t]*use[ \t]+Class::HPLOO(?:(\W.*?);|;)/s );
1347            
1348 0           $file_init =~ s/(?:^|\n)[ \t]*use[ \t]+Class::HPLOO(?:\W.*?;|;)//s ;
1349            
1350 0           $import_args = join ("", (eval($import_args))) ;
1351 0           $import_args =~ s/\W/ /gs ;
1352 0           $import_args =~ s/\s+/ /gs ;
1353            
1354 0           $file_init = "use Class::HPLOO qw(build $import_args);\n" . $file_init ;
1355            
1356 0           $BUILD_PM_FILE = $pm_file ;
1357 0           $BUILD_PM_VERSION = $pm_version ;
1358            
1359 0           open (my $fh,">$pm_file") ;
1360 0           print $fh $file_init ;
1361 0           close ($fh) ;
1362            
1363 0           my ($path,$file) = ( $pm_file =~ /(?:(.*)[\\\/]|^)([^\\\/]+)$/s );
1364            
1365             {
1366 0           unshift (@INC, $path) ;
  0            
1367            
1368 0           my $pack = $file ;
1369 0           $pack =~ s/\.pm$//s ;
1370            
1371 0           eval(" use $pack ") ;
1372            
1373 0           delete $INC{$pack} ;
1374 0           shift (@INC) ;
1375             }
1376            
1377 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
1378 0           $year += 1900 ;
1379 0           ++$mon ;
1380            
1381 0 0         $sec = "0$sec" if $sec < 10 ;
1382 0 0         $min = "0$min" if $min < 10 ;
1383 0 0         $hour = "0$hour" if $hour < 10 ;
1384 0 0         $mday = "0$mday" if $mday < 10 ;
1385 0 0         $mon = "0$mon" if $mon < 10 ;
1386            
1387 0           my $code = qq`#############################################################################
1388             ## This file was generated automatically by Class::HPLOO/$Class::HPLOO::VERSION
1389             ##
1390             ## Original file: $hploo_file
1391             ## Generation date: $year-$mon-$mday $hour:$min:$sec
1392             ##
1393             ## ** Do not change this file, use the original HPLOO source! **
1394             #############################################################################
1395             ` . $BUILD ;
1396            
1397 0           $BUILD = undef ;
1398            
1399 0           my $epod ;
1400 0           eval(q` require ePod `);
1401 0 0         if ( !$@ ) { $epod = new ePod( over_size => 4 ) ;}
  0            
1402            
1403 0 0 0       if ( $file_end ne '' && $epod && $epod->VERSION >= 0.03 && $epod->is_epod($file_end) ) {
      0        
      0        
1404 0           $file_end = $epod->epod2pod($file_end) ;
1405 0           $file_end =~ s/^\n//s ;
1406             }
1407            
1408 0           $code .= $file_splitter . $file_end ;
1409            
1410 0           $code =~ s/\r\n?/\n/gs ;
1411            
1412 0           open ($fh,">$pm_file") ;
1413 0           print $fh $code ;
1414 0           close ($fh) ;
1415            
1416 0           return $code ;
1417             }
1418            
1419             #######
1420             # END #
1421             #######
1422            
1423             1;
1424            
1425            
1426             __END__