kernel: disable FW_LOADER_USER_HELPER_FALLBACK
[people/pmueller/ipfire-2.x.git] / config / mpfire / perl / Readonly.pm
CommitLineData
83d20a45
CS
1=for gpg
2-----BEGIN PGP SIGNED MESSAGE-----
3Hash: SHA1
4
5- -----BEGIN PGP SIGNED MESSAGE-----
6Hash: SHA1
7
8=head1 NAME
9
10Readonly - Facility for creating read-only scalars, arrays, hashes.
11
12=head1 VERSION
13
14This documentation describes version 1.03 of Readonly.pm, April 20, 2004.
15
16=cut
17
18# Rest of documentation is after __END__.
19
20use 5.005;
21use strict;
22#use warnings;
23#no warnings 'uninitialized';
24
25package Readonly;
26$Readonly::VERSION = '1.03'; # Also change in the documentation!
27
28# Autocroak (Thanks, MJD)
29# Only load Carp.pm if module is croaking.
30sub croak
31{
32 require Carp;
33 goto &Carp::croak;
34}
35
36# These functions may be overridden by Readonly::XS, if installed.
37sub is_sv_readonly ($) { 0 }
38sub make_sv_readonly ($) { die "make_sv_readonly called but not overridden" }
39use vars qw/$XSokay/; # Set to true in Readonly::XS, if available
40
41# Common error messages, or portions thereof
42use vars qw/$MODIFY $REASSIGN $ODDHASH/;
43$MODIFY = 'Modification of a read-only value attempted';
44$REASSIGN = 'Attempt to reassign a readonly';
45$ODDHASH = 'May not store an odd number of values in a hash';
46
47# See if we can use the XS stuff.
48$Readonly::XS::MAGIC_COOKIE = "Do NOT use or require Readonly::XS unless you're me.";
49eval 'use Readonly::XS';
50
51
52# ----------------
53# Read-only scalars
54# ----------------
55package Readonly::Scalar;
56
57sub TIESCALAR
58{
59 my $whence = (caller 2)[3]; # Check if naughty user is trying to tie directly.
60 Readonly::croak "Invalid tie" unless $whence && $whence =~ /^Readonly::(?:Scalar1?|Readonly)$/;
61 my $class = shift;
62 Readonly::croak "No value specified for readonly scalar" unless @_;
63 Readonly::croak "Too many values specified for readonly scalar" unless @_ == 1;
64
65 my $value = shift;
66 return bless \$value, $class;
67}
68
69sub FETCH
70{
71 my $self = shift;
72 return $$self;
73}
74
75*STORE = *UNTIE =
76 sub {Readonly::croak $Readonly::MODIFY};
77
78
79# ----------------
80# Read-only arrays
81# ----------------
82package Readonly::Array;
83
84sub TIEARRAY
85{
86 my $whence = (caller 1)[3]; # Check if naughty user is trying to tie directly.
87 Readonly::croak "Invalid tie" unless $whence =~ /^Readonly::Array1?$/;
88 my $class = shift;
89 my @self = @_;
90
91 return bless \@self, $class;
92}
93
94sub FETCH
95{
96 my $self = shift;
97 my $index = shift;
98 return $self->[$index];
99}
100
101sub FETCHSIZE
102{
103 my $self = shift;
104 return scalar @$self;
105}
106
107BEGIN {
108 eval q{
109 sub EXISTS
110 {
111 my $self = shift;
112 my $index = shift;
113 return exists $self->[$index];
114 }
115 } if $] >= 5.006; # couldn't do "exists" on arrays before then
116}
117
118*STORE = *STORESIZE = *EXTEND = *PUSH = *POP = *UNSHIFT = *SHIFT = *SPLICE = *CLEAR = *UNTIE =
119 sub {Readonly::croak $Readonly::MODIFY};
120
121
122# ----------------
123# Read-only hashes
124# ----------------
125package Readonly::Hash;
126
127sub TIEHASH
128{
129 my $whence = (caller 1)[3]; # Check if naughty user is trying to tie directly.
130 Readonly::croak "Invalid tie" unless $whence =~ /^Readonly::Hash1?$/;
131
132 my $class = shift;
133 # must have an even number of values
134 Readonly::croak $Readonly::ODDHASH unless (@_ %2 == 0);
135
136 my %self = @_;
137 return bless \%self, $class;
138}
139
140sub FETCH
141{
142 my $self = shift;
143 my $key = shift;
144
145 return $self->{$key};
146}
147
148sub EXISTS
149{
150 my $self = shift;
151 my $key = shift;
152 return exists $self->{$key};
153}
154
155sub FIRSTKEY
156{
157 my $self = shift;
158 my $dummy = keys %$self;
159 return scalar each %$self;
160}
161
162sub NEXTKEY
163{
164 my $self = shift;
165 return scalar each %$self;
166}
167
168*STORE = *DELETE = *CLEAR = *UNTIE =
169 sub {Readonly::croak $Readonly::MODIFY};
170
171
172# ----------------------------------------------------------------
173# Main package, containing convenience functions (so callers won't
174# have to explicitly tie the variables themselves).
175# ----------------------------------------------------------------
176package Readonly;
177use Exporter;
178use vars qw/@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS/;
179push @ISA, 'Exporter';
180push @EXPORT, qw/Readonly/;
181push @EXPORT_OK, qw/Scalar Array Hash Scalar1 Array1 Hash1/;
182
183# Predeclare the following, so we can use them recursively
184sub Scalar ($$);
185sub Array (\@;@);
186sub Hash (\%;@);
187
188# Returns true if a string begins with "Readonly::"
189# Used to prevent reassignment of Readonly variables.
190sub _is_badtype
191{
192 my $type = $_[0];
193 return lc $type if $type =~ s/^Readonly:://;
194 return;
195}
196
197# Shallow Readonly scalar
198sub Scalar1 ($$)
199{
200 croak "$REASSIGN scalar" if is_sv_readonly $_[0];
201 my $badtype = _is_badtype (ref tied $_[0]);
202 croak "$REASSIGN $badtype" if $badtype;
203
204 # xs method: flag scalar as readonly
205 if ($XSokay)
206 {
207 $_[0] = $_[1];
208 make_sv_readonly $_[0];
209 return;
210 }
211
212 # pure-perl method: tied scalar
213 my $tieobj = eval {tie $_[0], 'Readonly::Scalar', $_[1]};
214 if ($@)
215 {
216 croak "$REASSIGN scalar" if substr($@,0,43) eq $MODIFY;
217 die $@; # some other error?
218 }
219 return $tieobj;
220}
221
222# Shallow Readonly array
223sub Array1 (\@;@)
224{
225 my $badtype = _is_badtype (ref tied $_[0]);
226 croak "$REASSIGN $badtype" if $badtype;
227
228 my $aref = shift;
229 return tie @$aref, 'Readonly::Array', @_;
230}
231
232# Shallow Readonly hash
233sub Hash1 (\%;@)
234{
235 my $badtype = _is_badtype (ref tied $_[0]);
236 croak "$REASSIGN $badtype" if $badtype;
237
238 my $href = shift;
239
240 # If only one value, and it's a hashref, expand it
241 if (@_ == 1 && ref $_[0] eq 'HASH')
242 {
243 return tie %$href, 'Readonly::Hash', %{$_[0]};
244 }
245
246 # otherwise, must have an even number of values
247 croak $ODDHASH unless (@_%2 == 0);
248
249 return tie %$href, 'Readonly::Hash', @_;
250}
251
252# Deep Readonly scalar
253sub Scalar ($$)
254{
255 croak "$REASSIGN scalar" if is_sv_readonly $_[0];
256 my $badtype = _is_badtype (ref tied $_[0]);
257 croak "$REASSIGN $badtype" if $badtype;
258
259 my $value = $_[1];
260
261 # Recursively check passed element for references; if any, make them Readonly
262 foreach ($value)
263 {
264 if (ref eq 'SCALAR') {Scalar my $v => $$_; $_ = \$v}
265 elsif (ref eq 'ARRAY') {Array my @v => @$_; $_ = \@v}
266 elsif (ref eq 'HASH') {Hash my %v => $_; $_ = \%v}
267 }
268
269 # xs method: flag scalar as readonly
270 if ($XSokay)
271 {
272 $_[0] = $value;
273 make_sv_readonly $_[0];
274 return;
275 }
276
277 # pure-perl method: tied scalar
278 my $tieobj = eval {tie $_[0], 'Readonly::Scalar', $value};
279 if ($@)
280 {
281 croak "$REASSIGN scalar" if substr($@,0,43) eq $MODIFY;
282 die $@; # some other error?
283 }
284 return $tieobj;
285}
286
287# Deep Readonly array
288sub Array (\@;@)
289{
290 my $badtype = _is_badtype (ref tied @{$_[0]});
291 croak "$REASSIGN $badtype" if $badtype;
292
293 my $aref = shift;
294 my @values = @_;
295
296 # Recursively check passed elements for references; if any, make them Readonly
297 foreach (@values)
298 {
299 if (ref eq 'SCALAR') {Scalar my $v => $$_; $_ = \$v}
300 elsif (ref eq 'ARRAY') {Array my @v => @$_; $_ = \@v}
301 elsif (ref eq 'HASH') {Hash my %v => $_; $_ = \%v}
302 }
303 # Lastly, tie the passed reference
304 return tie @$aref, 'Readonly::Array', @values;
305}
306
307# Deep Readonly hash
308sub Hash (\%;@)
309{
310 my $badtype = _is_badtype (ref tied %{$_[0]});
311 croak "$REASSIGN $badtype" if $badtype;
312
313 my $href = shift;
314 my @values = @_;
315
316 # If only one value, and it's a hashref, expand it
317 if (@_ == 1 && ref $_[0] eq 'HASH')
318 {
319 @values = %{$_[0]};
320 }
321
322 # otherwise, must have an even number of values
323 croak $ODDHASH unless (@values %2 == 0);
324
325 # Recursively check passed elements for references; if any, make them Readonly
326 foreach (@values)
327 {
328 if (ref eq 'SCALAR') {Scalar my $v => $$_; $_ = \$v}
329 elsif (ref eq 'ARRAY') {Array my @v => @$_; $_ = \@v}
330 elsif (ref eq 'HASH') {Hash my %v => $_; $_ = \%v}
331 }
332
333 return tie %$href, 'Readonly::Hash', @values;
334}
335
336
337# Common entry-point for all supported data types
338eval q{sub Readonly} . ( $] < 5.008 ? '' : '(\[$@%]@)' ) . <<'SUB_READONLY';
339{
340 if (ref $_[0] eq 'SCALAR')
341 {
342 croak $MODIFY if is_sv_readonly ${$_[0]};
343 my $badtype = _is_badtype (ref tied ${$_[0]});
344 croak "$REASSIGN $badtype" if $badtype;
345 croak "Readonly scalar must have only one value" if @_ > 2;
346
347 my $tieobj = eval {tie ${$_[0]}, 'Readonly::Scalar', $_[1]};
348 # Tie may have failed because user tried to tie a constant, or we screwed up somehow.
349 if ($@)
350 {
351 croak $MODIFY if $@ =~ /^$MODIFY at/; # Point the finger at the user.
352 die "$@\n"; # Not a modify read-only message; must be our fault.
353 }
354 return $tieobj;
355 }
356 elsif (ref $_[0] eq 'ARRAY')
357 {
358 my $aref = shift;
359 return Array @$aref, @_;
360 }
361 elsif (ref $_[0] eq 'HASH')
362 {
363 my $href = shift;
364 croak $ODDHASH if @_%2 != 0 && !(@_ == 1 && ref $_[0] eq 'HASH');
365 return Hash %$href, @_;
366 }
367 elsif (ref $_[0])
368 {
369 croak "Readonly only supports scalar, array, and hash variables.";
370 }
371 else
372 {
373 croak "First argument to Readonly must be a reference.";
374 }
375}
376SUB_READONLY
377
378
3791;
380__END__
381
382=head1 SYNOPSIS
383
384 use Readonly;
385
386 # Read-only scalar
387 Readonly::Scalar $sca => $initial_value;
388 Readonly::Scalar my $sca => $initial_value;
389
390 # Read-only array
391 Readonly::Array @arr => @values;
392 Readonly::Array my @arr => @values;
393
394 # Read-only hash
395 Readonly::Hash %has => (key => value, key => value, ...);
396 Readonly::Hash my %has => (key => value, key => value, ...);
397 # or:
398 Readonly::Hash %has => {key => value, key => value, ...};
399
400 # You can use the read-only variables like any regular variables:
401 print $sca;
402 $something = $sca + $arr[2];
403 next if $has{$some_key};
404
405 # But if you try to modify a value, your program will die:
406 $sca = 7;
407 push @arr, 'seven';
408 delete $has{key};
409 # The error message is "Modification of a read-only value
410attempted"
411
412 # Alternate form (Perl 5.8 and later)
413 Readonly $sca => $initial_value;
414 Readonly my $sca => $initial_value;
415 Readonly @arr => @values;
416 Readonly my @arr => @values;
417 Readonly %has => (key => value, key => value, ...);
418 Readonly my %has => (key => value, key => value, ...);
419 # Alternate form (for Perls earlier than v5.8)
420 Readonly \$sca => $initial_value;
421 Readonly \my $sca => $initial_value;
422 Readonly \@arr => @values;
423 Readonly \my @arr => @values;
424 Readonly \%has => (key => value, key => value, ...);
425 Readonly \my %has => (key => value, key => value, ...);
426
427
428=head1 DESCRIPTION
429
430This is a facility for creating non-modifiable variables. This is
431useful for configuration files, headers, etc. It can also be useful
432as a development and debugging tool, for catching updates to variables
433that should not be changed.
434
435If any of the values you pass to C<Scalar>, C<Array>, or C<Hash> are
436references, then those functions recurse over the data structures,
437marking everything as Readonly. Usually, this is what you want: the
438entire structure nonmodifiable. If you want only the top level to be
439Readonly, use the alternate C<Scalar1>, C<Array1> and C<Hash1>
440functions.
441
442Please note that most users of Readonly will also want to install a
443companion module Readonly::XS. See the L</CONS> section below for more
444details.
445
446=head1 COMPARISON WITH "use constant"
447
448Perl provides a facility for creating constant values, via the "use
449constant" pragma. There are several problems with this pragma.
450
451=over 2
452
453=item *
454
455The constants created have no leading $ or @ character.
456
457=item *
458
459These constants cannot be interpolated into strings.
460
461=item *
462
463Syntax can get dicey sometimes. For example:
464
465 use constant CARRAY => (2, 3, 5, 7, 11, 13);
466 $a_prime = CARRAY[2]; # wrong!
467 $a_prime = (CARRAY)[2]; # right -- MUST use parentheses
468
469=item *
470
471You have to be very careful in places where barewords are allowed.
472For example:
473
474 use constant SOME_KEY => 'key';
475 %hash = (key => 'value', other_key => 'other_value');
476 $some_value = $hash{SOME_KEY}; # wrong!
477 $some_value = $hash{+SOME_KEY}; # right
478
479(who thinks to use a unary plus when using a hash?)
480
481=item *
482
483C<use constant> works for scalars and arrays, not hashes.
484
485=item *
486
487These constants are global ot the package in which they're declared;
488cannot be lexically scoped.
489
490=item *
491
492Works only at compile time.
493
494=item *
495
496Can be overridden:
497
498 use constant PI => 3.14159;
499 ...
500 use constant PI => 2.71828;
501
502(this does generate a warning, however, if you have warnings enabled).
503
504=item *
505
506It is very difficult to make and use deep structures (complex data
507structures) with C<use constant>.
508
509=back
510
511=head1 COMPARISON WITH TYPEGLOB CONSTANTS
512
513Another popular way to create read-only scalars is to modify the symbol
514table entry for the variable by using a typeglob:
515
516 *a = \'value';
517
518This works fine, but it only works for global variables ("my"
519variables have no symbol table entry). Also, the following similar
520constructs do B<not> work:
521
522 *a = [1, 2, 3]; # Does NOT create a read-only array
523 *a = { a => 'A'}; # Does NOT create a read-only hash
524
525=head1 PROS
526
527Readonly.pm, on the other hand, will work with global variables and
528with lexical ("my") variables. It will create scalars, arrays, or
529hashes, all of which look and work like normal, read-write Perl
530variables. You can use them in scalar context, in list context; you
531can take references to them, pass them to functions, anything.
532
533Readonly.pm also works well with complex data structures, allowing you
534to tag the whole structure as nonmodifiable, or just the top level.
535
536Also, Readonly variables may not be reassigned. The following code
537will die:
538
539 Readonly::Scalar $pi => 3.14159;
540 ...
541 Readonly::Scalar $pi => 2.71828;
542
543=head1 CONS
544
545Readonly.pm does impose a performance penalty. It's pretty slow. How
546slow? Run the C<benchmark.pl> script that comes with Readonly. On my
547test system, "use constant", typeglob constants, and regular
548read/write Perl variables were all about the same speed, and
549Readonly.pm constants were about 1/20 the speed.
550
551However, there is relief. There is a companion module available,
552Readonly::XS. If it is installed on your system, Readonly.pm uses it
553to make read-only scalars much faster. With Readonly::XS, Readonly
554scalars are as fast as the other types of variables. Readonly arrays
555and hashes will still be relatively slow. But it's likely that most
556of your Readonly variables will be scalars.
557
558If you can't use Readonly::XS (for example, if you don't have a C
559compiler, or your perl is statically linked and you don't want to
560re-link it), you have to decide whether the benefits of Readonly
561variables outweigh the speed issue. For most configuration variables
562(and other things that Readonly is likely to be useful for), the speed
563issue is probably not really a big problem. But benchmark your
564program if it might be. If it turns out to be a problem, you may
565still want to use Readonly.pm during development, to catch changes to
566variables that should not be changed, and then remove it for
567production:
568
569 # For testing:
570 Readonly::Scalar $Foo_Directory => '/usr/local/foo';
571 Readonly::Scalar $Bar_Directory => '/usr/local/bar';
572 # $Foo_Directory = '/usr/local/foo';
573 # $Bar_Directory = '/usr/local/bar';
574
575 # For production:
576 # Readonly::Scalar $Foo_Directory => '/usr/local/foo';
577 # Readonly::Scalar $Bar_Directory => '/usr/local/bar';
578 $Foo_Directory = '/usr/local/foo';
579 $Bar_Directory = '/usr/local/bar';
580
581
582=head1 FUNCTIONS
583
584=over 4
585
586=item Readonly::Scalar $var => $value;
587
588Creates a nonmodifiable scalar, C<$var>, and assigns a value of
589C<$value> to it. Thereafter, its value may not be changed. Any
590attempt to modify the value will cause your program to die.
591
592A value I<must> be supplied. If you want the variable to have
593C<undef> as its value, you must specify C<undef>.
594
595If C<$value> is a reference to a scalar, array, or hash, then this
596function will mark the scalar, array, or hash it points to as being
597Readonly as well, and it will recursively traverse the structure,
598marking the whole thing as Readonly. Usually, this is what you want.
599However, if you want only the C<$value> marked as Readonly, use
600C<Scalar1>.
601
602If $var is already a Readonly variable, the program will die with
603an error about reassigning Readonly variables.
604
605=item Readonly::Array @arr => (value, value, ...);
606
607Creates a nonmodifiable array, C<@arr>, and assigns the specified list
608of values to it. Thereafter, none of its values may be changed; the
609array may not be lengthened or shortened or spliced. Any attempt to
610do so will cause your program to die.
611
612If any of the values passed is a reference to a scalar, array, or hash,
613then this function will mark the scalar, array, or hash it points to as
614being Readonly as well, and it will recursively traverse the structure,
615marking the whole thing as Readonly. Usually, this is what you want.
616However, if you want only the hash C<%@arr> itself marked as Readonly,
617use C<Array1>.
618
619If @arr is already a Readonly variable, the program will die with
620an error about reassigning Readonly variables.
621
622=item Readonly::Hash %h => (key => value, key => value, ...);
623
624=item Readonly::Hash %h => {key => value, key => value, ...};
625
626Creates a nonmodifiable hash, C<%h>, and assigns the specified keys
627and values to it. Thereafter, its keys or values may not be changed.
628Any attempt to do so will cause your program to die.
629
630A list of keys and values may be specified (with parentheses in the
631synopsis above), or a hash reference may be specified (curly braces in
632the synopsis above). If a list is specified, it must have an even
633number of elements, or the function will die.
634
635If any of the values is a reference to a scalar, array, or hash, then
636this function will mark the scalar, array, or hash it points to as
637being Readonly as well, and it will recursively traverse the
638structure, marking the whole thing as Readonly. Usually, this is what
639you want. However, if you want only the hash C<%h> itself marked as
640Readonly, use C<Hash1>.
641
642If %h is already a Readonly variable, the program will die with
643an error about reassigning Readonly variables.
644
645=item Readonly $var => $value;
646
647=item Readonly @arr => (value, value, ...);
648
649=item Readonly %h => (key => value, ...);
650
651=item Readonly %h => {key => value, ...};
652
653The C<Readonly> function is an alternate to the C<Scalar>, C<Array>,
654and C<Hash> functions. It has the advantage (if you consider it an
655advantage) of being one function. That may make your program look
656neater, if you're initializing a whole bunch of constants at once.
657You may or may not prefer this uniform style.
658
659It has the disadvantage of having a slightly different syntax for
660versions of Perl prior to 5.8. For earlier versions, you must supply
661a backslash, because it requires a reference as the first parameter.
662
663 Readonly \$var => $value;
664 Readonly \@arr => (value, value, ...);
665 Readonly \%h => (key => value, ...);
666 Readonly \%h => {key => value, ...};
667
668You may or may not consider this ugly.
669
670=item Readonly::Scalar1 $var => $value;
671
672=item Readonly::Array1 @arr => (value, value, ...);
673
674=item Readonly::Hash1 %h => (key => value, key => value, ...);
675
676=item Readonly::Hash1 %h => {key => value, key => value, ...};
677
678These alternate functions create shallow Readonly variables, instead
679of deep ones. For example:
680
681 Readonly::Array1 @shal => (1, 2, {perl=>'Rules', java=>'Bites'}, 4, 5);
682 Readonly::Array @deep => (1, 2, {perl=>'Rules', java=>'Bites'}, 4, 5);
683
684 $shal[1] = 7; # error
685 $shal[2]{APL}='Weird'; # Allowed! since the hash isn't Readonly
686 $deep[1] = 7; # error
687 $deep[2]{APL}='Weird'; # error, since the hash is Readonly
688
689
690=back
691
692
693=head1 EXAMPLES
694
695 # SCALARS:
696
697 # A plain old read-only value
698 Readonly::Scalar $a => "A string value";
699
700 # The value need not be a compile-time constant:
701 Readonly::Scalar $a => $computed_value;
702
703
704 # ARRAYS:
705
706 # A read-only array:
707 Readonly::Array @a => (1, 2, 3, 4);
708
709 # The parentheses are optional:
710 Readonly::Array @a => 1, 2, 3, 4;
711
712 # You can use Perl's built-in array quoting syntax:
713 Readonly::Array @a => qw/1 2 3 4/;
714
715 # You can initialize a read-only array from a variable one:
716 Readonly::Array @a => @computed_values;
717
718 # A read-only array can be empty, too:
719 Readonly::Array @a => ();
720 Readonly::Array @a; # equivalent
721
722
723 # HASHES
724
725 # Typical usage:
726 Readonly::Hash %a => (key1 => 'value1', key2 => 'value2');
727
728 # A read-only hash can be initialized from a variable one:
729 Readonly::Hash %a => %computed_values;
730
731 # A read-only hash can be empty:
732 Readonly::Hash %a => ();
733 Readonly::Hash %a; # equivalent
734
735 # If you pass an odd number of values, the program will die:
736 Readonly::Hash %a => (key1 => 'value1', "value2");
737 --> dies with "May not store an odd number of values in a hash"
738
739
740=head1 EXPORTS
741
742By default, this module exports the following symbol into the calling
743program's namespace:
744
745 Readonly
746
747The following symbols are available for import into your program, if
748you like:
749
750 Scalar Scalar1
751 Array Array1
752 Hash Hash1
753
754
755=head1 REQUIREMENTS
756
757 Perl 5.000
758 Carp.pm (included with Perl)
759 Exporter.pm (included with Perl)
760
761 Readonly::XS is recommended but not required.
762
763=head1 ACKNOWLEDGEMENTS
764
765Thanks to Slaven Rezic for the idea of one common function
766(Readonly) for all three types of variables (13 April 2002).
767
768Thanks to Ernest Lergon for the idea (and initial code) for
769deeply-Readonly data structures (21 May 2002).
770
771Thanks to Damian Conway for the idea (and code) for making the
772Readonly function work a lot smoother under perl 5.8+.
773
774
775=head1 AUTHOR / COPYRIGHT
776
777Eric J. Roode, roode@cpan.org
778
779Copyright (c) 2001-2004 by Eric J. Roode. All Rights Reserved. This
780module is free software; you can redistribute it and/or modify it under
781the same terms as Perl itself.
782
783If you have suggestions for improvement, please drop me a line. If
784you make improvements to this software, I ask that you please send me
785a copy of your changes. Thanks.
786
787Readonly.pm is made from 100% recycled electrons. No animals were
788harmed during the development and testing of this module. Not sold
789in stores! Readonly::XS sold separately. Void where prohibited.
790
791=cut
792
793=begin gpg
794
795-----BEGIN PGP SIGNATURE-----
796Version: GnuPG v1.2.4 (MingW32)
797
798iD8DBQFAhaGCY96i4h5M0egRAg++AJ0ar4ncojbOp0OOc2wo+E/1cBn5cQCg9eP9
799qTzAC87PuyKB+vrcRykrDbo=
800=39Ny
801-----END PGP SIGNATURE-----
802
803=cut