Install msysDVLPR-1.0.0-alpha-1
[msysgit.git] / share / autoconf / Autom4te / Struct.pm
blobc388a6473dfcfc05b8759006468aaa454af9d6de
1 # autoconf -- create `configure' using m4 macros
2 # Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2, or (at your option)
7 # any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 # 02110-1301, USA.
19 # This file is basically Perl 5.6's Class::Struct, but made compatible
20 # with Perl 5.5. If someday this has to be updated, be sure to rename
21 # all the occurrences of Class::Struct into Autom4te::Struct, otherwise
22 # if we `use' a Perl module (e.g., File::stat) that uses Class::Struct,
23 # we would have two packages defining the same symbols. Boom.
25 ###############################################################
26 # The main copy of this file is in Automake's CVS repository. #
27 # Updates should be sent to automake-patches@gnu.org. #
28 ###############################################################
30 package Autom4te::Struct;
32 ## See POD after __END__
34 use 5.005_03;
36 use strict;
37 use vars qw(@ISA @EXPORT $VERSION);
39 use Carp;
41 require Exporter;
42 @ISA = qw(Exporter);
43 @EXPORT = qw(struct);
45 $VERSION = '0.58';
47 ## Tested on 5.002 and 5.003 without class membership tests:
48 my $CHECK_CLASS_MEMBERSHIP = ($] >= 5.003_95);
50 my $print = 0;
51 sub printem {
52 if (@_) { $print = shift }
53 else { $print++ }
57 package Autom4te::Struct::Tie_ISA;
59 sub TIEARRAY {
60 my $class = shift;
61 return bless [], $class;
64 sub STORE {
65 my ($self, $index, $value) = @_;
66 Autom4te::Struct::_subclass_error();
69 sub FETCH {
70 my ($self, $index) = @_;
71 $self->[$index];
74 sub FETCHSIZE {
75 my $self = shift;
76 return scalar(@$self);
79 sub DESTROY { }
82 sub struct {
84 # Determine parameter list structure, one of:
85 # struct( class => [ element-list ])
86 # struct( class => { element-list })
87 # struct( element-list )
88 # Latter form assumes current package name as struct name.
90 my ($class, @decls);
91 my $base_type = ref $_[1];
92 if ( $base_type eq 'HASH' ) {
93 $class = shift;
94 @decls = %{shift()};
95 _usage_error() if @_;
97 elsif ( $base_type eq 'ARRAY' ) {
98 $class = shift;
99 @decls = @{shift()};
100 _usage_error() if @_;
102 else {
103 $base_type = 'ARRAY';
104 $class = (caller())[0];
105 @decls = @_;
107 _usage_error() if @decls % 2 == 1;
109 # Ensure we are not, and will not be, a subclass.
111 my $isa = do {
112 no strict 'refs';
113 \@{$class . '::ISA'};
115 _subclass_error() if @$isa;
116 tie @$isa, 'Autom4te::Struct::Tie_ISA';
118 # Create constructor.
120 croak "function 'new' already defined in package $class"
121 if do { no strict 'refs'; defined &{$class . "::new"} };
123 my @methods = ();
124 my %refs = ();
125 my %arrays = ();
126 my %hashes = ();
127 my %classes = ();
128 my $got_class = 0;
129 my $out = '';
131 $out = "{\n package $class;\n use Carp;\n sub new {\n";
132 $out .= " my (\$class, \%init) = \@_;\n";
133 $out .= " \$class = __PACKAGE__ unless \@_;\n";
135 my $cnt = 0;
136 my $idx = 0;
137 my( $cmt, $name, $type, $elem );
139 if( $base_type eq 'HASH' ){
140 $out .= " my(\$r) = {};\n";
141 $cmt = '';
143 elsif( $base_type eq 'ARRAY' ){
144 $out .= " my(\$r) = [];\n";
146 while( $idx < @decls ){
147 $name = $decls[$idx];
148 $type = $decls[$idx+1];
149 push( @methods, $name );
150 if( $base_type eq 'HASH' ){
151 $elem = "{'${class}::$name'}";
153 elsif( $base_type eq 'ARRAY' ){
154 $elem = "[$cnt]";
155 ++$cnt;
156 $cmt = " # $name";
158 if( $type =~ /^\*(.)/ ){
159 $refs{$name}++;
160 $type = $1;
162 my $init = "defined(\$init{'$name'}) ? \$init{'$name'} :";
163 if( $type eq '@' ){
164 $out .= " croak 'Initializer for $name must be array reference'\n";
165 $out .= " if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'ARRAY';\n";
166 $out .= " \$r->$elem = $init [];$cmt\n";
167 $arrays{$name}++;
169 elsif( $type eq '%' ){
170 $out .= " croak 'Initializer for $name must be hash reference'\n";
171 $out .= " if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'HASH';\n";
172 $out .= " \$r->$elem = $init {};$cmt\n";
173 $hashes{$name}++;
175 elsif ( $type eq '$') {
176 $out .= " \$r->$elem = $init undef;$cmt\n";
178 elsif( $type =~ /^\w+(?:::\w+)*$/ ){
179 $init = "defined(\$init{'$name'}) ? \%{\$init{'$name'}} : ()";
180 $out .= " croak 'Initializer for $name must be hash reference'\n";
181 $out .= " if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'HASH';\n";
182 $out .= " \$r->$elem = '${type}'->new($init);$cmt\n";
183 $classes{$name} = $type;
184 $got_class = 1;
186 else{
187 croak "'$type' is not a valid struct element type";
189 $idx += 2;
191 $out .= " bless \$r, \$class;\n }\n";
193 # Create accessor methods.
195 my( $pre, $pst, $sel );
196 $cnt = 0;
197 foreach $name (@methods){
198 if ( do { no strict 'refs'; defined &{$class . "::$name"} } ) {
199 carp "function '$name' already defined, overrides struct accessor method";
201 else {
202 $pre = $pst = $cmt = $sel = '';
203 if( defined $refs{$name} ){
204 $pre = "\\(";
205 $pst = ")";
206 $cmt = " # returns ref";
208 $out .= " sub $name {$cmt\n my \$r = shift;\n";
209 if( $base_type eq 'ARRAY' ){
210 $elem = "[$cnt]";
211 ++$cnt;
213 elsif( $base_type eq 'HASH' ){
214 $elem = "{'${class}::$name'}";
216 if( defined $arrays{$name} ){
217 $out .= " my \$i;\n";
218 $out .= " \@_ ? (\$i = shift) : return \$r->$elem;\n";
219 $sel = "->[\$i]";
221 elsif( defined $hashes{$name} ){
222 $out .= " my \$i;\n";
223 $out .= " \@_ ? (\$i = shift) : return \$r->$elem;\n";
224 $sel = "->{\$i}";
226 elsif( defined $classes{$name} ){
227 if ( $CHECK_CLASS_MEMBERSHIP ) {
228 $out .= " croak '$name argument is wrong class' if \@_ && ! UNIVERSAL::isa(\$_[0], '$classes{$name}');\n";
231 $out .= " croak 'Too many args to $name' if \@_ > 1;\n";
232 $out .= " \@_ ? ($pre\$r->$elem$sel = shift$pst) : $pre\$r->$elem$sel$pst;\n";
233 $out .= " }\n";
236 $out .= "}\n1;\n";
238 print $out if $print;
239 my $result = eval $out;
240 carp $@ if $@;
243 sub _usage_error {
244 confess "struct usage error";
247 sub _subclass_error {
248 croak 'struct class cannot be a subclass (@ISA not allowed)';
251 1; # for require
254 __END__
256 =head1 NAME
258 Autom4te::Struct - declare struct-like datatypes as Perl classes
260 =head1 SYNOPSIS
262 use Autom4te::Struct;
263 # declare struct, based on array:
264 struct( CLASS_NAME => [ ELEMENT_NAME => ELEMENT_TYPE, ... ]);
265 # declare struct, based on hash:
266 struct( CLASS_NAME => { ELEMENT_NAME => ELEMENT_TYPE, ... });
268 package CLASS_NAME;
269 use Autom4te::Struct;
270 # declare struct, based on array, implicit class name:
271 struct( ELEMENT_NAME => ELEMENT_TYPE, ... );
274 package Myobj;
275 use Autom4te::Struct;
276 # declare struct with four types of elements:
277 struct( s => '$', a => '@', h => '%', c => 'My_Other_Class' );
279 $obj = new Myobj; # constructor
281 # scalar type accessor:
282 $element_value = $obj->s; # element value
283 $obj->s('new value'); # assign to element
285 # array type accessor:
286 $ary_ref = $obj->a; # reference to whole array
287 $ary_element_value = $obj->a(2); # array element value
288 $obj->a(2, 'new value'); # assign to array element
290 # hash type accessor:
291 $hash_ref = $obj->h; # reference to whole hash
292 $hash_element_value = $obj->h('x'); # hash element value
293 $obj->h('x', 'new value'); # assign to hash element
295 # class type accessor:
296 $element_value = $obj->c; # object reference
297 $obj->c->method(...); # call method of object
298 $obj->c(new My_Other_Class); # assign a new object
301 =head1 DESCRIPTION
303 C<Autom4te::Struct> exports a single function, C<struct>.
304 Given a list of element names and types, and optionally
305 a class name, C<struct> creates a Perl 5 class that implements
306 a "struct-like" data structure.
308 The new class is given a constructor method, C<new>, for creating
309 struct objects.
311 Each element in the struct data has an accessor method, which is
312 used to assign to the element and to fetch its value. The
313 default accessor can be overridden by declaring a C<sub> of the
314 same name in the package. (See Example 2.)
316 Each element's type can be scalar, array, hash, or class.
319 =head2 The C<struct()> function
321 The C<struct> function has three forms of parameter-list.
323 struct( CLASS_NAME => [ ELEMENT_LIST ]);
324 struct( CLASS_NAME => { ELEMENT_LIST });
325 struct( ELEMENT_LIST );
327 The first and second forms explicitly identify the name of the
328 class being created. The third form assumes the current package
329 name as the class name.
331 An object of a class created by the first and third forms is
332 based on an array, whereas an object of a class created by the
333 second form is based on a hash. The array-based forms will be
334 somewhat faster and smaller; the hash-based forms are more
335 flexible.
337 The class created by C<struct> must not be a subclass of another
338 class other than C<UNIVERSAL>.
340 It can, however, be used as a superclass for other classes. To facilitate
341 this, the generated constructor method uses a two-argument blessing.
342 Furthermore, if the class is hash-based, the key of each element is
343 prefixed with the class name (see I<Perl Cookbook>, Recipe 13.12).
345 A function named C<new> must not be explicitly defined in a class
346 created by C<struct>.
348 The I<ELEMENT_LIST> has the form
350 NAME => TYPE, ...
352 Each name-type pair declares one element of the struct. Each
353 element name will be defined as an accessor method unless a
354 method by that name is explicitly defined; in the latter case, a
355 warning is issued if the warning flag (B<-w>) is set.
358 =head2 Element Types and Accessor Methods
360 The four element types -- scalar, array, hash, and class -- are
361 represented by strings -- C<'$'>, C<'@'>, C<'%'>, and a class name --
362 optionally preceded by a C<'*'>.
364 The accessor method provided by C<struct> for an element depends
365 on the declared type of the element.
367 =over
369 =item Scalar (C<'$'> or C<'*$'>)
371 The element is a scalar, and by default is initialized to C<undef>
372 (but see L<Initializing with new>).
374 The accessor's argument, if any, is assigned to the element.
376 If the element type is C<'$'>, the value of the element (after
377 assignment) is returned. If the element type is C<'*$'>, a reference
378 to the element is returned.
380 =item Array (C<'@'> or C<'*@'>)
382 The element is an array, initialized by default to C<()>.
384 With no argument, the accessor returns a reference to the
385 element's whole array (whether or not the element was
386 specified as C<'@'> or C<'*@'>).
388 With one or two arguments, the first argument is an index
389 specifying one element of the array; the second argument, if
390 present, is assigned to the array element. If the element type
391 is C<'@'>, the accessor returns the array element value. If the
392 element type is C<'*@'>, a reference to the array element is
393 returned.
395 =item Hash (C<'%'> or C<'*%'>)
397 The element is a hash, initialized by default to C<()>.
399 With no argument, the accessor returns a reference to the
400 element's whole hash (whether or not the element was
401 specified as C<'%'> or C<'*%'>).
403 With one or two arguments, the first argument is a key specifying
404 one element of the hash; the second argument, if present, is
405 assigned to the hash element. If the element type is C<'%'>, the
406 accessor returns the hash element value. If the element type is
407 C<'*%'>, a reference to the hash element is returned.
409 =item Class (C<'Class_Name'> or C<'*Class_Name'>)
411 The element's value must be a reference blessed to the named
412 class or to one of its subclasses. The element is initialized to
413 the result of calling the C<new> constructor of the named class.
415 The accessor's argument, if any, is assigned to the element. The
416 accessor will C<croak> if this is not an appropriate object
417 reference.
419 If the element type does not start with a C<'*'>, the accessor
420 returns the element value (after assignment). If the element type
421 starts with a C<'*'>, a reference to the element itself is returned.
423 =back
425 =head2 Initializing with C<new>
427 C<struct> always creates a constructor called C<new>. That constructor
428 may take a list of initializers for the various elements of the new
429 struct.
431 Each initializer is a pair of values: I<element name>C< =E<gt> >I<value>.
432 The initializer value for a scalar element is just a scalar value. The
433 initializer for an array element is an array reference. The initializer
434 for a hash is a hash reference.
436 The initializer for a class element is also a hash reference, and the
437 contents of that hash are passed to the element's own constructor.
439 See Example 3 below for an example of initialization.
442 =head1 EXAMPLES
444 =over
446 =item Example 1
448 Giving a struct element a class type that is also a struct is how
449 structs are nested. Here, C<timeval> represents a time (seconds and
450 microseconds), and C<rusage> has two elements, each of which is of
451 type C<timeval>.
453 use Autom4te::Struct;
455 struct( rusage => {
456 ru_utime => timeval, # seconds
457 ru_stime => timeval, # microseconds
460 struct( timeval => [
461 tv_secs => '$',
462 tv_usecs => '$',
465 # create an object:
466 my $t = new rusage;
468 # $t->ru_utime and $t->ru_stime are objects of type timeval.
469 # set $t->ru_utime to 100.0 sec and $t->ru_stime to 5.0 sec.
470 $t->ru_utime->tv_secs(100);
471 $t->ru_utime->tv_usecs(0);
472 $t->ru_stime->tv_secs(5);
473 $t->ru_stime->tv_usecs(0);
476 =item Example 2
478 An accessor function can be redefined in order to provide
479 additional checking of values, etc. Here, we want the C<count>
480 element always to be nonnegative, so we redefine the C<count>
481 accessor accordingly.
483 package MyObj;
484 use Autom4te::Struct;
486 # declare the struct
487 struct ( 'MyObj', { count => '$', stuff => '%' } );
489 # override the default accessor method for 'count'
490 sub count {
491 my $self = shift;
492 if ( @_ ) {
493 die 'count must be nonnegative' if $_[0] < 0;
494 $self->{'count'} = shift;
495 warn "Too many args to count" if @_;
497 return $self->{'count'};
500 package main;
501 $x = new MyObj;
502 print "\$x->count(5) = ", $x->count(5), "\n";
503 # prints '$x->count(5) = 5'
505 print "\$x->count = ", $x->count, "\n";
506 # prints '$x->count = 5'
508 print "\$x->count(-5) = ", $x->count(-5), "\n";
509 # dies due to negative argument!
511 =item Example 3
513 The constructor of a generated class can be passed a list
514 of I<element>=>I<value> pairs, with which to initialize the struct.
515 If no initializer is specified for a particular element, its default
516 initialization is performed instead. Initializers for non-existent
517 elements are silently ignored.
519 Note that the initializer for a nested struct is specified
520 as an anonymous hash of initializers, which is passed on to the nested
521 struct's constructor.
524 use Autom4te::Struct;
526 struct Breed =>
528 name => '$',
529 cross => '$',
532 struct Cat =>
534 name => '$',
535 kittens => '@',
536 markings => '%',
537 breed => 'Breed',
541 my $cat = Cat->new( name => 'Socks',
542 kittens => ['Monica', 'Kenneth'],
543 markings => { socks=>1, blaze=>"white" },
544 breed => { name=>'short-hair', cross=>1 },
547 print "Once a cat called ", $cat->name, "\n";
548 print "(which was a ", $cat->breed->name, ")\n";
549 print "had two kittens: ", join(' and ', @{$cat->kittens}), "\n";
551 =back
553 =head1 Author and Modification History
555 Modified by Akim Demaille, 2001-08-03
557 Rename as Autom4te::Struct to avoid name clashes with
558 Class::Struct.
560 Make it compatible with Perl 5.5.
562 Modified by Damian Conway, 1999-03-05, v0.58.
564 Added handling of hash-like arg list to class ctor.
566 Changed to two-argument blessing in ctor to support
567 derivation from created classes.
569 Added classname prefixes to keys in hash-based classes
570 (refer to "Perl Cookbook", Recipe 13.12 for rationale).
572 Corrected behavior of accessors for '*@' and '*%' struct
573 elements. Package now implements documented behavior when
574 returning a reference to an entire hash or array element.
575 Previously these were returned as a reference to a reference
576 to the element.
579 Renamed to C<Class::Struct> and modified by Jim Miner, 1997-04-02.
581 members() function removed.
582 Documentation corrected and extended.
583 Use of struct() in a subclass prohibited.
584 User definition of accessor allowed.
585 Treatment of '*' in element types corrected.
586 Treatment of classes as element types corrected.
587 Class name to struct() made optional.
588 Diagnostic checks added.
591 Originally C<Class::Template> by Dean Roehrich.
593 # Template.pm --- struct/member template builder
594 # 12mar95
595 # Dean Roehrich
597 # changes/bugs fixed since 28nov94 version:
598 # - podified
599 # changes/bugs fixed since 21nov94 version:
600 # - Fixed examples.
601 # changes/bugs fixed since 02sep94 version:
602 # - Moved to Class::Template.
603 # changes/bugs fixed since 20feb94 version:
604 # - Updated to be a more proper module.
605 # - Added "use strict".
606 # - Bug in build_methods, was using @var when @$var needed.
607 # - Now using my() rather than local().
609 # Uses perl5 classes to create nested data types.
610 # This is offered as one implementation of Tom Christiansen's "structs.pl"
611 # idea.
613 =cut
615 ### Setup "GNU" style for perl-mode and cperl-mode.
616 ## Local Variables:
617 ## perl-indent-level: 2
618 ## perl-continued-statement-offset: 2
619 ## perl-continued-brace-offset: 0
620 ## perl-brace-offset: 0
621 ## perl-brace-imaginary-offset: 0
622 ## perl-label-offset: -2
623 ## cperl-indent-level: 2
624 ## cperl-brace-offset: 0
625 ## cperl-continued-brace-offset: 0
626 ## cperl-label-offset: -2
627 ## cperl-extra-newline-before-brace: t
628 ## cperl-merge-trailing-else: nil
629 ## cperl-continued-statement-offset: 2
630 ## End: