File Coverage

blib/lib/Class/Simple.pm
Criterion Covered Total %
statement 182 190 95.7
branch 64 78 82.0
condition 7 8 87.5
subroutine 33 33 100.0
pod 5 5 100.0
total 291 314 92.6


line stmt bran cond sub pod time code
1             #$Id: Simple.pm,v 1.29 2008/01/01 16:34:15 sullivan Exp $
2             #
3             # See the POD documentation starting towards the __END__ of this file.
4              
5             package Class::Simple;
6              
7 11     11   636400 use 5.008;
  11         136  
8 11     11   63 use strict;
  11         21  
  11         329  
9 11     11   86 use warnings;
  11         19  
  11         641  
10              
11             our $VERSION = '1.1';
12              
13 11     11   71 use Scalar::Util qw(refaddr);
  11         28  
  11         750  
14 11     11   65 use Carp;
  11         20  
  11         1059  
15             ## no critic
16 11     11   5308 use Class::ISA;
  11         25326  
  11         397  
17             ## use critic
18 11     11   72 use List::Util qw( first );
  11         23  
  11         1651  
19              
20             my %STORAGE;
21             my %PRIVATE;
22             my %READONLY;
23             my @internal_attributes = qw(CLASS);
24              
25             our $AUTOLOAD;
26              
27             sub AUTOLOAD
28             {
29 97     97   4007 my $self = shift;
30 97         197 my @args = @_;
31              
32 11     11   78 no strict 'refs';
  11         21  
  11         13816  
33              
34 97         613 $AUTOLOAD =~ /(.*)::((get|set|clear|raise|readonly)_)?(\w+)/;
35 97         237 my $pkg = $1;
36 97         144 my $full_method = $AUTOLOAD;
37 97   100     383 my $prefix = $3 || '';
38 97         347 my $attrib = $4;
39 97 100       236 $prefix = '' if ($attrib =~ /^_/);
40 97         210 my $store_as = $attrib;
41 97 100       231 $store_as =~ s/^_// unless $prefix;
42              
43 97 100       381 if (my $get_attributes = $self->can('ATTRIBUTES'))
44             {
45 12         36 my @attributes = &$get_attributes();
46 12         54 push(@attributes, @internal_attributes);
47             croak("$attrib is not a defined attribute in $pkg")
48 12 100   35   65 unless first {$_ eq $attrib} @attributes;
  35         89  
49             }
50              
51             #
52             # Make sure that if you add more special prefixes here,
53             # you add them to the $AUTOLOAD regex above, too.
54             #
55 95 100 66     506 if ($prefix eq 'set')
    100          
    100          
    100          
    100          
    100          
56             {
57 24         84 *{$AUTOLOAD} = sub
58             {
59 53     53   90 my $self = shift;
60              
61 53         140 my $ref = refaddr($self);
62             croak("$attrib is readonly: cannot set.")
63 53 100       383 if ($READONLY{$ref}->{$store_as});
64 51 50       159 if (@_ > 1) {
65             # Must be initialized (in new or init) as an array ref or hash ref.
66 0 0       0 if (ref $STORAGE{$ref}->{$store_as} eq 'ARRAY') {
    0          
67 0         0 @{$STORAGE{$ref}->{$store_as}}[$_[0]] = $_[1];
  0         0  
68 0         0 return (@{$STORAGE{$ref}->{$store_as}}[$_[0]]);
  0         0  
69             } elsif (ref $STORAGE{$ref}->{$store_as} eq 'HASH') {
70 0         0 $STORAGE{$ref}->{$store_as}->{$_[0]} = $_[1];
71 0         0 return ($STORAGE{$ref}->{$store_as}->{$_[0]});
72             }
73             } else {
74 51         256 return ($STORAGE{$ref}->{$store_as} = shift(@_));
75             }
76 24         131 };
77             }
78             elsif ($prefix eq 'get')
79             {
80 22         75 *{$AUTOLOAD} = sub
81             {
82 67     67   105 my $self = shift;
83              
84 67         148 my $ref = refaddr($self);
85 67         333 return ($STORAGE{$ref}->{$store_as});
86 22         102 };
87             }
88             #
89             # Bug #7528 in Perl keeps this from working.
90             # http://rt.perl.org/rt3/Public/Bug/Display.html?id=7528
91             # I could make people declare methods they want to use lv_
92             # with but that goes against the philosophy of being ::Simple.
93             #
94             # elsif ($prefix eq 'lv')
95             # {
96             # *{$AUTOLOAD} = sub : lvalue
97             # {
98             # my $self = shift;
99             #
100             # my $ref = refaddr($self);
101             # croak("$attrib is readonly: cannot set.")
102             # if ($READONLY{$ref}->{$store_as});
103             # return ($STORAGE{$ref}->{$store_as});
104             # };
105             # }
106             elsif ($prefix eq 'clear')
107             {
108 1         2 my $setter = "set_$attrib";
109 1         5 *{$AUTOLOAD} = sub
110             {
111 2     2   4 my $self = shift;
112              
113 2         6 return ($self->$setter(undef));
114 1         5 };
115             }
116             elsif ($prefix eq 'raise')
117             {
118 1         3 my $setter = "set_$attrib";
119 1         5 *{$AUTOLOAD} = sub
120             {
121 2     2   5 my $self = shift;
122              
123 2         6 return ($self->$setter(1));
124 1         4 };
125             }
126             elsif ($prefix eq 'readonly')
127             {
128 13         38 my $setter = "set_$attrib";
129 13         62 *{$AUTOLOAD} = sub
130             {
131 24     24   42 my $self = shift;
132              
133 24         199 my $ret = $self->$setter(@_);
134 24         61 my $ref = refaddr($self);
135 24         66 $READONLY{$ref}->{$store_as} = 1;
136 24         53 return ($ret);
137 13         70 };
138             }
139             #
140             # All methods starting with '_' can only be called from
141             # within their package. Not inheritable, which makes
142             # the test easier than something privatized..
143             #
144             # Note that we cannot just call get_ and set_ here
145             # because if someone writes their own get_foo and then
146             # _foo is called, _foo will call set_foo, which will
147             # probably store something with _foo, which will call
148             # set_foo, etc. Sure wish we could somehow share
149             # code with get_ and set_, though.
150             #
151             elsif (!$prefix && ($attrib =~ /^_/))
152             {
153 11 100       65 if (my $method = $pkg->can($attrib))
154             {
155 3         10 return &$method($self, @args);
156             }
157              
158 8         29 *{$AUTOLOAD} = sub
159             {
160 18     18   1217 my $self = shift;
161              
162 18 100       39 croak("Cannot call $attrib: Private method to $pkg.")
163             unless ($pkg->isa(Class::Simple::_my_caller()));
164 14         36 my $ref = refaddr($self);
165 14 100       34 if (scalar(@_))
166             {
167             croak("$attrib is readonly: cannot set.")
168 6 50       21 if ($READONLY{$ref}->{$store_as});
169 6         37 return ($STORAGE{$ref}->{$store_as} =shift(@_));
170             }
171             else
172             {
173 8         52 return ($STORAGE{$ref}->{$store_as});
174             }
175 8         51 };
176             }
177             else
178             {
179 23         83 my $setter = "set_$store_as";
180 23         66 my $getter = "get_$store_as";
181 23         105 *{$AUTOLOAD} = sub
182             {
183 74     74   6370 my $self = shift;
184              
185 74 100       369 return (scalar(@_)
186             ? $self->$setter(@_)
187             : $self->$getter());
188 23         122 };
189             }
190 92         198 return (&{$AUTOLOAD}($self, @args));
  92         233  
191             }
192              
193              
194              
195             #
196             # Call all the DEMOLISH()es and then delete from %STORAGE.
197             #
198             sub DESTROY
199             {
200 22     22   4041 my $self = shift;
201              
202 22         90 $self->_travel_isa('DESTROY', 'DEMOLISH');
203 22         66 my $ref = refaddr($self);
204 22 50       99 delete($STORAGE{$ref}) if exists($STORAGE{$ref});
205 22 100       1318 delete($READONLY{$ref}) if exists($READONLY{$ref});
206             }
207              
208              
209              
210             #
211             # Travel up the class's @ISA and run $func, if we can.
212             # To keep from running a sub more than once we flag
213             # $storage in %STORAGE.
214             #
215             sub _travel_isa
216             {
217 42     42   67 my $self = shift;
218 42         66 my $storage = shift;
219 42         56 my $func = shift;
220              
221 42         101 my $ref = refaddr($self);
222 42 50       217 $STORAGE{$ref}->{$storage}= {} unless exists($STORAGE{$ref}->{$storage});
223 42         160 my @path = reverse(Class::ISA::super_path($self->CLASS));
224 42         2210 foreach my $c (@path)
225             {
226 60 100       151 next if ($c eq __PACKAGE__);
227 20 50       77 next if $STORAGE{$ref}->{$storage}->{$c}++;
228              
229 20         40 my $cn = "${c}::can";
230 20 100       133 if (my $in = $c->can($func))
231             {
232 7         31 $self->$in(@_);
233             }
234             }
235 42 100       243 $self->$func(@_) if $self->can($func);;
236             }
237              
238              
239              
240             #
241             # Make a scalar. Bless it. Call init.
242             #
243             sub new
244             {
245 22     22 1 9175 my $class = shift;
246              
247             #
248             # Support for NONEW.
249             #
250             {
251 11     11   106 no strict 'refs';
  11         26  
  11         1723  
  22         55  
252 22         59 my $classy = "${class}::";
253             croak("Cannot call new() in $class.")
254 22 100       44 if exists(${$classy}{'NONEW'});
  22         261  
255             }
256              
257             #
258             # This is how you get an anonymous scalar.
259             #
260 21         45 my $self = \do{my $anon_scalar};
  21         53  
261 21         44 bless($self, $class);
262 21         132 $self->readonly_CLASS($class);
263              
264 21         119 $self->init(@_);
265 20         61 return ($self);
266             }
267              
268              
269              
270             #
271             # Flag the given method(s) as being private to the class
272             # (and its children unless overridden).
273             #
274             sub privatize
275             {
276 8     8 1 1993 my $class = shift;
277              
278 8         26 foreach my $method (@_)
279             {
280 11     11   128 no strict 'refs';
  11         22  
  11         2186  
281              
282             #
283             # Can't privatize something that is already private
284             # from an ancestor.
285             #
286 9         26 foreach my $private_class (keys(%PRIVATE))
287             {
288 7 100       23 next unless $PRIVATE{$private_class}->{$method};
289 1 50       187 croak("Cannot privatize ${class}::$method: already private in $private_class.")
290             unless $private_class->isa($class);
291             }
292              
293             #
294             # Can't retroactively make privatize something.
295             #
296 8         19 my $called_by = _my_caller();
297 8 100       203 croak("Attempt to privatize ${class}::$method from $called_by. Can only privatize in your own class.")
298             if ($class ne $called_by);
299 7         34 $PRIVATE{$class}->{$method} = 1;
300              
301             #
302             # Although it is duplication of code (which I hope
303             # to come up with a clever way to avoid at some point),
304             # it is a better solution to have privatize() create
305             # these subs now. Otherwise, having the private test
306             # done in AUTOLOAD gets to be fairly convoluted.
307             # Defining them here makes the tests a lot simpler.
308             #
309 7         23 my $getter = "${class}::get_$method";
310 7         16 my $setter = "${class}::set_$method";
311 7         16 my $generic = "${class}::$method";
312 7         41 *{$getter} = sub
313             {
314 1     1   2 my $self = shift;
315              
316 11     11   80 no strict 'refs';
  11         27  
  11         1305  
317 1 50       3 croak("Cannot call $getter: Private method to $class.")
318             unless $class->isa(Class::Simple::_my_caller());
319 1         3 my $ref = refaddr($self);
320 1         15 return ($STORAGE{$ref}->{$method});
321 7         45 };
322             *$setter = sub
323             {
324 5     5   11 my $self = shift;
325              
326 11     11   75 no strict 'refs';
  11         20  
  11         1664  
327 5 50       17 croak("Cannot call $setter: Private method to $class.")
328             unless $class->isa(Class::Simple::_my_caller());
329 5         13 my $ref = refaddr($self);
330             croak("$method is readonly: cannot set.")
331 5 100       318 if ($READONLY{$ref}->{$method});
332 4         13 return ($STORAGE{$ref}->{$method} = shift(@_));
333 7         49 };
334             *$generic = sub
335             {
336 6     6   814 my $self = shift;
337              
338 11     11   95 no strict 'refs';
  11         33  
  11         5525  
339 6 100       14 croak("Cannot call $generic: Private method to $class.")
340             unless $class->isa(Class::Simple::_my_caller());
341 3         12 my $ref = refaddr($self);
342 3 100       16 return (scalar(@_)
343             ? $self->$setter(@_)
344             : $self->$getter());
345 7         58 };
346 7         20 my $ugen = "_${generic}";
347 7         52 *$ugen = *$generic;
348             }
349             }
350              
351              
352              
353             #
354             # Bubble up the caller() stack until we leave this package.
355             #
356             sub _my_caller
357             {
358 38     38   125 for (my $i = 0; my $c = caller($i); ++$i)
359             {
360 92 100       1511 return ($c) unless $c eq __PACKAGE__;
361             }
362 0         0 return (__PACKAGE__); # Shouldn't get here but just in case
363             }
364              
365              
366              
367             #
368             # This will not be called if the child classes have
369             # their own. In case they don't (and they really shouldn't
370             # because they should be using BUILD() instead), this is the default.
371             #
372             sub init
373             {
374 21     21 1 37 my $self = shift;
375              
376             #
377             # If we see an even number of arguments, assume they are initializers.
378             # Don't like that behavior? Override init().
379             #
380 21 100 100     106 if (scalar(@_) && scalar(@_) % 2 == 0) {
381 2         7 my %args = @_;
382 2         10 while ( my ($k, $v) = each(%args) )
383             {
384 3         20 $self->$k($v);
385             }
386             }
387              
388 20         115 $self->_travel_isa('init', 'BUILD', @_);
389 20         103 return ($self);
390             }
391              
392              
393              
394             ##
395             ## toJson() and fromJson() are DUMP and SLURP equivalents for JSON.
396             ## I'm not sure if they're all that useful yet so they're silently
397             ## lurking here for now.
398             ##
399             #sub toJson
400             #{
401             #my $self = shift;
402             #
403             # croak("Cannot use toJson(): module JSON::XS not found.\n")
404             # unless (eval 'require JSON::XS; 1');
405             #
406             # my $ref = refaddr($self);
407             # my $json = JSON::XS->new();
408             # return $json->encode($STORAGE{$ref});
409             #}
410             #
411             #
412             #
413             #sub fromJson
414             #{
415             #my $self = shift;
416             #my $str = shift;
417             #
418             # return $self unless $str;
419             #
420             # croak("Cannot use fromJson(): module JSON::XS not found.\n")
421             # unless (eval 'require JSON::XS; 1');
422             #
423             # my $json = JSON::XS->new();
424             # my $obj = $json->decode($str);
425             # my $ref = refaddr($self);
426             # $STORAGE{$ref} = $obj;
427             #
428             # return ($self);
429             #}
430              
431              
432              
433             #
434             # Callback for Storable to serialize objects.
435             #
436             sub STORABLE_freeze
437             {
438 1     1 1 49 my $self = shift;
439 1         2 my $cloning = shift;
440              
441 1 50       69 croak("Cannot use STORABLE_freeze(): module Storable not found.\n")
442             unless (eval 'require Storable; 1');
443              
444 1         5 my $ref = refaddr($self);
445 1         6 return Storable::freeze($STORAGE{$ref});
446             }
447              
448              
449              
450             #
451             # Callback for Storable to reconstitute serialized objects.
452             #
453             sub STORABLE_thaw
454             {
455 1     1 1 180 my $self = shift;
456 1         2 my $cloning = shift;
457 1         3 my $serialized = shift;
458              
459 1 50       58 croak("Cannot use STORABLE_thaw(): module Storable not found.\n")
460             unless (eval 'require Storable; 1');
461              
462 1         5 my $ref = refaddr($self);
463 1         5 $STORAGE{$ref} = Storable::thaw($serialized);
464             }
465              
466             1;
467             __END__
468              
469             =head1 NAME
470              
471             Class::Simple - Simple Object-Oriented Base Class
472              
473             =head1 SYNOPSIS
474              
475             package Foo:
476             use base qw(Class::Simple);
477              
478             BEGIN
479             {
480             Foo->privatize(qw(attrib1 attrib2)); # ...or not.
481             }
482             my $obj = Foo->new();
483              
484             $obj->attrib(1); # The same as...
485             $obj->set_attrib(1); # ...this.
486              
487             my $var = $obj->get_attrib(); # The same as...
488             $var = $obj->attrib; # ...this.
489              
490             $obj->raise_attrib(); # The same as...
491             $obj->set_attrib(1); # ...this.
492              
493             $obj->clear_attrib(); # The same as...
494             $obj->set_attrib(undef); # ...this
495             $obj->attrib(undef); # ...and this.
496              
497             $obj->readonly_attrib(4);
498              
499             sub foo
500             {
501             my $self = shift;
502             my $value = shift;
503              
504             $self->_foo($value);
505             do_other_things(@_);
506             ...
507             }
508              
509             my $str = Storable::freeze($obj);
510             # Save $str to a file
511             ...
512             # Read contents of file into $new_str
513             $new_obj = Storable::thaw($new_str);
514              
515             sub BUILD
516             {
517             my $self = shift;
518              
519             # Various initializations
520             }
521              
522             =head1 DESCRIPTION
523              
524             This is a simple object-oriented base class. There are plenty of others
525             that are much more thorough and whatnot but sometimes I want something
526             simple so I can get just going (no doubt because I am a simple guy)
527             so I use this.
528              
529             What do I mean by simple? First off, I don't want to have to list out
530             all my methods beforehand. I just want to use them (Yeah, yeah, it doesn't
531             catch typos...well, by default--see B<ATTRIBUTES()> below).
532             Next, I want to be able to
533             call my methods by $obj->foo(1) or $obj->set_foo(1), by $obj->foo() or
534             $obj->get_foo(). Don't tell ME I have to use get_ and set_ (I would just
535             override that restriction in Class::Std anyway). Simple!
536              
537             I did want some neat features, though, so these are inside-out objects
538             (meaning the object isn't simply a hash so you can't just go in and
539             muck with attributtes outside of methods),
540             privatization of methods is supported, as is serialization out and back
541             in again.
542              
543             It's important to note, though, that one does not have to use the extra
544             features to use B<Class::Simple>. All you need to get going is:
545              
546             package MyPackage;
547             use base qw(Class::Simple);
548              
549             And that's it. To use it?:
550              
551             use MyPackage;
552              
553             my $obj = MyPackage->new();
554             $obj->set_attr($value);
555              
556             Heck, you don't even need that much:
557              
558             use Class::Simple;
559              
560             my $obj = Class::Simple->new();
561             $obj->set_attr($value);
562              
563             Why would you want to use a (not quite) anonymous object?
564             Well, you can use it to simulate the interface of a class
565             to do some testing and debugging.
566              
567             =head2 Garbage Collection
568              
569             Garbage collection is handled automatically by B<Class::Simple>.
570             The only thing the user has to worry about is cleaning up dangling
571             and circular references.
572              
573             Example:
574              
575             my $a = Foo->new();
576             {
577             my $b = Foo->new();
578             $b->set_yell('Ouch!');
579             $a->next = $b;
580             }
581             print $a->next->yell;
582              
583             Even though B<$b> goes out of scope when the block exits,
584             B<$a->next()> still refers to it so B<DESTROY> is never called on B<$b>
585             and "Ouch!" is printed.
586             Why is B<$a> referring to an out-of-scope object in the first place?
587             Programmer error--there is only so much that B<Class::Simple> can fix :-).
588              
589             =head1 METHODS
590              
591             =head2 Class Methods
592              
593             =over 4
594              
595             =item B<new(>[attr => val...]B<)>
596              
597             Returns the object and calls B<BUILD()>.
598              
599             If key/value pairs are included, the keys will be treated as attributes
600             and the values will be used to initialize its respective attribute.
601              
602             =item B<privatize(>qw(method1 method2 ...B<)>
603              
604             Mark the given methods as being private to the class.
605             They will only be accessible to the class or its ancestors.
606             Make sure this is called before you start instantiating objects.
607             It should probably be put in a B<BEGIN> or B<INIT> block.
608              
609             =back
610              
611             =head2 Optional User-defined Methods
612              
613             =over 4
614              
615             =item B<BUILD()>
616              
617             If there is initialization that you would like to do after an
618             object is created, this is the place to do it.
619              
620             =item B<NONEW()>
621              
622             If this is defined in a class, B<new()> will not work for that class.
623             You can use this in an abstract class when only concrete classes
624             descended from the abstract class should have B<new()>.
625              
626             =item B<DEMOLISH()>
627              
628             If you want to write your own DESTROY, don't.
629             Do it here in DEMOLISH, which will be called by DESTROY.
630              
631             =item B<ATTRIBUTES()>
632              
633             Did I say we can't catch typos?
634             Well, that's only partially true.
635             If this is defined in your class, it needs to return an array of
636             attribute names.
637             If it is defined, only the attributes returned will be allowed
638             to be used.
639             Trying to get or set an attribute not in the list will be a fatal error.
640             Note that this is an B<optional> method.
641             You B<do not> have to define your attributes ahead of time to use
642             Class::Simple.
643             This provides an optional layer of error-checking.
644              
645             =back
646              
647             =head2 Object Methods
648              
649             =over 4
650              
651             =item B<init()>
652              
653             I lied above when I wrote that B<new()> called B<BUILD()>.
654             It really calls B<init()> and B<init()> calls B<BUILD()>.
655             Actually, it calls all the B<BUILD()>s of all the ancestor classes
656             (in a recursive, left-to-right fashion).
657             If, for some reason, you do not want to do that,
658             simply write your own B<init()> and this will be short-circuited.
659              
660             =item B<CLASS>
661              
662             The class this object was blessed in.
663             Really used for internal housekeeping but I might as well let you
664             know about it in case it would be helpful.
665             It is readonly (see below).
666              
667             =item B<STORABLE_freeze>
668              
669             See B<Serialization> below.
670              
671             =item B<STORABLE_thaw>
672              
673             See B<Serialization> below.
674              
675             =back
676              
677             If you want an attribute named "foo", just start using the following
678             (no pre-declaration is needed):
679              
680             =over 4
681              
682             =item B<foo(>[val]B<)>
683              
684             Without any parameters, it returns the value of foo.
685             With a parameter, it sets foo to the value of the parameter and returns it.
686             Even if that value is undef.
687              
688             =item B<get_foo()>
689              
690             Returns the value of foo.
691              
692             =item B<set_foo(>valB<)>
693              
694             Sets foo to the value of the given parameter and returns it.
695              
696             =item B<raise_foo()>
697              
698             The idea is that if foo is a flag, this raises the flag by
699             setting foo to 1 and returns it.
700              
701             =item B<clear_foo()>
702              
703             Set foo to undef and returns it.
704              
705             =item B<readonly_foo(>valB<)>
706              
707             Set foo to the given value, then disallow any further changing of foo.
708             Returns the value.
709              
710             =item B<_foo(>[val]B<)>
711              
712             If you have an attribute foo but you want to override the default method,
713             you can use B<_foo> to keep the data.
714             That way you don't have to roll your own way of storing the data,
715             possibly breaking inside-out.
716             Underscore methods are automatically privatized.
717             Also works as B<set__foo> and B<get__foo>.
718              
719             =back
720              
721             =head2 Serialization
722              
723             There are hooks here to work with L<Storable> to serialize objects.
724             To serialize a Class::Simple-derived object:
725              
726             use Storable;
727              
728             my $serialized = Storable::freeze($obj);
729              
730             To reconstitute an object saved with B<freeze()>:
731              
732             my $new_obj = Storable::thaw($serialized_str);
733              
734             =head1 CAVEATS
735              
736             If an ancestor class has a B<foo> attribute, children cannot have their
737             own B<foo>. They get their parent's B<foo>.
738              
739             I don't actually have a need for DUMP and SLURP but I thought they
740             would be nice to include.
741             If you know how I can make them useful for someone who would actually
742             use them, let me know.
743              
744             =head1 SEE ALSO
745              
746             L<Class::Std> is an excellent introduction to the concept
747             of inside-out objects in Perl
748             (they are referred to as the "flyweight pattern" in Damian Conway's
749             I<Object Oriented Perl>).
750             Many things here, like the name B<DEMOLISH()>, were shamelessly stolen from it.
751             Standing on the shoulders of giants and all that.
752              
753             L<Storable>
754              
755             =head1 AUTHOR
756              
757             Michael Sullivan, E<lt>perldude@mac.comE<gt>
758              
759             =head1 COPYRIGHT AND LICENSE
760              
761             Copyright (C) 2007 by Michael Sullivan
762              
763             This library is free software; you can redistribute it and/or modify
764             it under the same terms as Perl itself, either Perl version 5.8.6 or,
765             at your option, any later version of Perl 5 you may have available.
766              
767             =cut