Release 0.9.14.
[wine/multimedia.git] / tools / winapi / c_type.pm
blobf1ee7baa2df8642ce0c37078fcdcd9a3ceeb495c
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 package c_type;
21 use strict;
23 use output qw($output);
25 sub _refresh($);
27 sub new($) {
28 my $proto = shift;
29 my $class = ref($proto) || $proto;
30 my $self = {};
31 bless ($self, $class);
33 return $self;
36 ########################################################################
37 # set_find_align_callback
39 sub set_find_align_callback($$) {
40 my $self = shift;
42 my $find_align = \${$self->{FIND_ALIGN}};
44 $$find_align = shift;
47 ########################################################################
48 # set_find_kind_callback
50 sub set_find_kind_callback($$) {
51 my $self = shift;
53 my $find_kind = \${$self->{FIND_KIND}};
55 $$find_kind = shift;
58 ########################################################################
59 # set_find_size_callback
61 sub set_find_size_callback($$) {
62 my $self = shift;
64 my $find_size = \${$self->{FIND_SIZE}};
66 $$find_size = shift;
69 ########################################################################
70 # set_find_count_callback
72 sub set_find_count_callback($$) {
73 my $self = shift;
75 my $find_count = \${$self->{FIND_COUNT}};
77 $$find_count = shift;
80 sub kind($$) {
81 my $self = shift;
82 my $kind = \${$self->{KIND}};
83 my $dirty = \${$self->{DIRTY}};
85 local $_ = shift;
87 if(defined($_)) { $$kind = $_; $$dirty = 1; }
89 if (!defined($$kind)) {
90 $self->_refresh();
93 return $$kind;
96 sub _name($$) {
97 my $self = shift;
98 my $_name = \${$self->{_NAME}};
99 my $dirty = \${$self->{DIRTY}};
101 local $_ = shift;
103 if(defined($_)) { $$_name = $_; $$dirty = 1; }
105 return $$_name;
108 sub name($$) {
109 my $self = shift;
110 my $name = \${$self->{NAME}};
111 my $dirty = \${$self->{DIRTY}};
113 local $_ = shift;
115 if(defined($_)) { $$name = $_; $$dirty = 1; }
117 if($$name) {
118 return $$name;
119 } else {
120 my $kind = \${$self->{KIND}};
121 my $_name = \${$self->{_NAME}};
123 return "$$kind $$_name";
127 sub pack($$) {
128 my $self = shift;
129 my $pack = \${$self->{PACK}};
130 my $dirty = \${$self->{DIRTY}};
132 local $_ = shift;
134 if(defined($_)) { $$pack = $_; $$dirty = 1; }
136 return $$pack;
139 sub align($) {
140 my $self = shift;
142 my $align = \${$self->{ALIGN}};
144 $self->_refresh();
146 return $$align;
149 sub fields($) {
150 my $self = shift;
152 my $count = $self->field_count;
154 my @fields = ();
155 for (my $n = 0; $n < $count; $n++) {
156 my $field = 'c_type_field'->new($self, $n);
157 push @fields, $field;
159 return @fields;
162 sub field_base_sizes($) {
163 my $self = shift;
164 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
166 $self->_refresh();
168 return $$field_base_sizes;
171 sub field_aligns($) {
172 my $self = shift;
173 my $field_aligns = \${$self->{FIELD_ALIGNS}};
175 $self->_refresh();
177 return $$field_aligns;
180 sub field_count($) {
181 my $self = shift;
182 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
184 my @field_type_names = @{$$field_type_names};
185 my $count = scalar(@field_type_names);
187 return $count;
190 sub field_names($$) {
191 my $self = shift;
192 my $field_names = \${$self->{FIELD_NAMES}};
193 my $dirty = \${$self->{DIRTY}};
195 local $_ = shift;
197 if(defined($_)) { $$field_names = $_; $$dirty = 1; }
199 return $$field_names;
202 sub field_offsets($) {
203 my $self = shift;
204 my $field_offsets = \${$self->{FIELD_OFFSETS}};
206 $self->_refresh();
208 return $$field_offsets;
211 sub field_sizes($) {
212 my $self = shift;
213 my $field_sizes = \${$self->{FIELD_SIZES}};
215 $self->_refresh();
217 return $$field_sizes;
220 sub field_type_names($$) {
221 my $self = shift;
222 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
223 my $dirty = \${$self->{DIRTY}};
225 local $_ = shift;
227 if(defined($_)) { $$field_type_names = $_; $$dirty = 1; }
229 return $$field_type_names;
232 sub size($) {
233 my $self = shift;
235 my $size = \${$self->{SIZE}};
237 $self->_refresh();
239 return $$size;
242 sub _refresh($) {
243 my $self = shift;
245 my $dirty = \${$self->{DIRTY}};
247 return if !$$dirty;
249 my $find_align = \${$self->{FIND_ALIGN}};
250 my $find_kind = \${$self->{FIND_KIND}};
251 my $find_size = \${$self->{FIND_SIZE}};
252 my $find_count = \${$self->{FIND_COUNT}};
254 my $align = \${$self->{ALIGN}};
255 my $kind = \${$self->{KIND}};
256 my $size = \${$self->{SIZE}};
257 my $field_aligns = \${$self->{FIELD_ALIGNS}};
258 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
259 my $field_offsets = \${$self->{FIELD_OFFSETS}};
260 my $field_sizes = \${$self->{FIELD_SIZES}};
262 my $pack = $self->pack;
263 $pack = 8 if !defined($pack);
265 my $max_field_align = 0;
267 my $offset = 0;
268 my $bitfield_size = 0;
269 my $bitfield_bits = 0;
271 my $n = 0;
272 foreach my $field ($self->fields) {
273 my $type_name = $field->type_name;
275 my $bits;
276 my $count;
277 if ($type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/)
279 $count = $2;
280 $bits = $3;
282 my $declspec_align;
283 if ($type_name =~ s/\s+DECLSPEC_ALIGN\((\d+)\)//)
285 $declspec_align=$1;
287 my $base_size = &$$find_size($type_name);
288 my $type_size=$base_size;
289 if (defined $count)
291 $count=&$$find_count($count) if ($count !~ /^\d+$/);
292 if (!defined $count)
294 $type_size=undef;
296 else
298 $type_size *= int($count);
301 if ($bitfield_size != 0)
303 if (($type_name eq "" and defined $bits and $bits == 0) or
304 (defined $type_size and $bitfield_size != $type_size) or
305 !defined $bits or
306 $bitfield_bits + $bits > 8 * $bitfield_size)
308 # This marks the end of the previous bitfield
309 $bitfield_size=0;
310 $bitfield_bits=0;
312 else
314 $bitfield_bits+=$bits;
315 $n++;
316 next;
320 $$align = &$$find_align($type_name);
321 $$align=$declspec_align if (defined $declspec_align);
323 if (defined $$align)
325 $$align = $pack if $$align > $pack;
326 $max_field_align = $$align if $$align > $max_field_align;
328 if ($offset % $$align != 0) {
329 $offset = (int($offset / $$align) + 1) * $$align;
333 if ($$kind !~ /^(?:struct|union)$/)
335 $$kind = &$$find_kind($type_name) || "";
338 if (!$type_size)
340 $$align = undef;
341 $$size = undef;
342 return;
345 $$$field_aligns[$n] = $$align;
346 $$$field_base_sizes[$n] = $base_size;
347 $$$field_offsets[$n] = $offset;
348 $$$field_sizes[$n] = $type_size;
349 $offset += $type_size;
351 if ($bits)
353 $bitfield_size=$type_size;
354 $bitfield_bits=$bits;
356 $n++;
359 $$align = $pack;
360 $$align = $max_field_align if $max_field_align < $pack;
362 $$size = $offset;
363 if ($$kind =~ /^(?:struct|union)$/) {
364 if ($$size % $$align != 0) {
365 $$size = (int($$size / $$align) + 1) * $$align;
369 $$dirty = 0;
372 package c_type_field;
374 sub new($$$) {
375 my $proto = shift;
376 my $class = ref($proto) || $proto;
377 my $self = {};
378 bless ($self, $class);
380 my $type = \${$self->{TYPE}};
381 my $number = \${$self->{NUMBER}};
383 $$type = shift;
384 $$number = shift;
386 return $self;
389 sub align($) {
390 my $self = shift;
391 my $type = \${$self->{TYPE}};
392 my $number = \${$self->{NUMBER}};
394 my $field_aligns = $$type->field_aligns;
396 return $$field_aligns[$$number];
399 sub base_size($) {
400 my $self = shift;
401 my $type = \${$self->{TYPE}};
402 my $number = \${$self->{NUMBER}};
404 my $field_base_sizes = $$type->field_base_sizes;
406 return $$field_base_sizes[$$number];
409 sub name($) {
410 my $self = shift;
411 my $type = \${$self->{TYPE}};
412 my $number = \${$self->{NUMBER}};
414 my $field_names = $$type->field_names;
416 return $$field_names[$$number];
419 sub offset($) {
420 my $self = shift;
421 my $type = \${$self->{TYPE}};
422 my $number = \${$self->{NUMBER}};
424 my $field_offsets = $$type->field_offsets;
426 return $$field_offsets[$$number];
429 sub size($) {
430 my $self = shift;
431 my $type = \${$self->{TYPE}};
432 my $number = \${$self->{NUMBER}};
434 my $field_sizes = $$type->field_sizes;
436 return $$field_sizes[$$number];
439 sub type_name($) {
440 my $self = shift;
441 my $type = \${$self->{TYPE}};
442 my $number = \${$self->{NUMBER}};
444 my $field_type_names = $$type->field_type_names;
446 return $$field_type_names[$$number];