2 # Copyright 2002 Patrik Stridvall
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library 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 GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 use output qw($output);
27 my $class = ref($proto) || $proto;
29 bless ($self, $class);
34 ########################################################################
35 # set_find_align_callback
37 sub set_find_align_callback {
40 my $find_align = \${$self->{FIND_ALIGN}};
45 ########################################################################
46 # set_find_size_callback
48 sub set_find_size_callback {
51 my $find_size = \${$self->{FIND_SIZE}};
58 my $kind = \${$self->{KIND}};
59 my $dirty = \${$self->{DIRTY}};
63 if(defined($_)) { $$kind = $_; $$dirty = 1; }
70 my $_name = \${$self->{_NAME}};
71 my $dirty = \${$self->{DIRTY}};
75 if(defined($_)) { $$_name = $_; $$dirty = 1; }
82 my $name = \${$self->{NAME}};
83 my $dirty = \${$self->{DIRTY}};
87 if(defined($_)) { $$name = $_; $$dirty = 1; }
92 my $kind = \${$self->{KIND}};
93 my $_name = \${$self->{_NAME}};
95 return "$$kind $$_name";
101 my $pack = \${$self->{PACK}};
102 my $dirty = \${$self->{DIRTY}};
106 if(defined($_)) { $$pack = $_; $$dirty = 1; }
114 my $align = \${$self->{ALIGN}};
124 my $count = $self->field_count;
127 for (my $n = 0; $n < $count; $n++) {
128 my $field = 'c_type_field'->new($self, $n);
129 push @fields, $field;
134 sub field_base_sizes {
136 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
140 return $$field_base_sizes;
145 my $field_aligns = \${$self->{FIELD_ALIGNS}};
149 return $$field_aligns;
154 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
156 my @field_type_names = @{$$field_type_names};
157 my $count = scalar(@field_type_names);
164 my $field_names = \${$self->{FIELD_NAMES}};
165 my $dirty = \${$self->{DIRTY}};
169 if(defined($_)) { $$field_names = $_; $$dirty = 1; }
171 return $$field_names;
176 my $field_offsets = \${$self->{FIELD_OFFSETS}};
180 return $$field_offsets;
185 my $field_sizes = \${$self->{FIELD_SIZES}};
189 return $$field_sizes;
192 sub field_type_names {
194 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
195 my $dirty = \${$self->{DIRTY}};
199 if(defined($_)) { $$field_type_names = $_; $$dirty = 1; }
201 return $$field_type_names;
207 my $size = \${$self->{SIZE}};
217 my $dirty = \${$self->{DIRTY}};
221 my $find_align = \${$self->{FIND_ALIGN}};
222 my $find_size = \${$self->{FIND_SIZE}};
224 my $align = \${$self->{ALIGN}};
225 my $kind = \${$self->{KIND}};
226 my $size = \${$self->{SIZE}};
227 my $field_aligns = \${$self->{FIELD_ALIGNS}};
228 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
229 my $field_offsets = \${$self->{FIELD_OFFSETS}};
230 my $field_sizes = \${$self->{FIELD_SIZES}};
232 my $pack = $self->pack;
234 my $max_field_align = 0;
240 foreach my $field ($self->fields) {
241 my $type_name = $field->type_name;
242 my $size = &$$find_size($type_name);
244 my $base_type_name = $type_name;
245 if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) {
249 my $base_size = &$$find_size($base_type_name);
250 my $align = &$$find_align($base_type_name);
252 if (defined($align)) {
253 $align = $pack if $align > $pack;
254 $max_field_align = $align if $align > $max_field_align;
256 if ($offset % $align != 0) {
257 $offset = (int($offset / $align) + 1) * $align;
261 if (!defined($size)) {
265 } elsif ($size >= 0) {
267 $offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack));
271 $$$field_aligns[$n] = $align;
272 $$$field_base_sizes[$n] = $base_size;
273 $$$field_offsets[$n] = $offset;
274 $$$field_sizes[$n] = $size;
278 $$$field_aligns[$n] = $align;
279 $$$field_base_sizes[$n] = $base_size;
280 $$$field_offsets[$n] = $offset;
281 $$$field_sizes[$n] = $size;
283 $offset_bits += -$size;
290 $$align = $max_field_align if $max_field_align < $pack;
293 if ($$kind =~ /^(?:struct|union)$/) {
294 if ($$size % $$align != 0) {
295 $$size = (int($$size / $$align) + 1) * $$align;
302 package c_type_field;
306 my $class = ref($proto) || $proto;
308 bless ($self, $class);
310 my $type = \${$self->{TYPE}};
311 my $number = \${$self->{NUMBER}};
321 my $type = \${$self->{TYPE}};
322 my $number = \${$self->{NUMBER}};
324 my $field_aligns = $$type->field_aligns;
326 return $$field_aligns[$$number];
331 my $type = \${$self->{TYPE}};
332 my $number = \${$self->{NUMBER}};
334 my $field_base_sizes = $$type->field_base_sizes;
336 return $$field_base_sizes[$$number];
341 my $type = \${$self->{TYPE}};
342 my $number = \${$self->{NUMBER}};
344 my $field_names = $$type->field_names;
346 return $$field_names[$$number];
351 my $type = \${$self->{TYPE}};
352 my $number = \${$self->{NUMBER}};
354 my $field_offsets = $$type->field_offsets;
356 return $$field_offsets[$$number];
361 my $type = \${$self->{TYPE}};
362 my $number = \${$self->{NUMBER}};
364 my $field_sizes = $$type->field_sizes;
366 return $$field_sizes[$$number];
371 my $type = \${$self->{TYPE}};
372 my $number = \${$self->{NUMBER}};
374 my $field_type_names = $$type->field_type_names;
376 return $$field_type_names[$$number];