push ac694015ba9a1d7cf8fc6346c6e51d4c35a62962
[wine/hacks.git] / tools / winapi / c_type.pm
blob0cf81bb0f43f0532a6dabb9b3db7e73309d814c8
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;
82 # Property setter / getter functions (each does both)
85 sub kind($;$)
87 my $self = shift;
88 my $kind = \${$self->{KIND}};
89 my $dirty = \${$self->{DIRTY}};
91 local $_ = shift;
93 if(defined($_)) { $$kind = $_; $$dirty = 1; }
95 if (!defined($$kind)) {
96 $self->_refresh();
99 return $$kind;
102 sub _name($;$)
104 my $self = shift;
105 my $_name = \${$self->{_NAME}};
106 my $dirty = \${$self->{DIRTY}};
108 local $_ = shift;
110 if(defined($_)) { $$_name = $_; $$dirty = 1; }
112 return $$_name;
115 sub name($;$)
117 my $self = shift;
118 my $name = \${$self->{NAME}};
119 my $dirty = \${$self->{DIRTY}};
121 local $_ = shift;
123 if(defined($_)) { $$name = $_; $$dirty = 1; }
125 if($$name) {
126 return $$name;
127 } else {
128 my $kind = \${$self->{KIND}};
129 my $_name = \${$self->{_NAME}};
131 return "$$kind $$_name";
135 sub pack($;$)
137 my $self = shift;
138 my $pack = \${$self->{PACK}};
139 my $dirty = \${$self->{DIRTY}};
141 local $_ = shift;
143 if(defined($_)) { $$pack = $_; $$dirty = 1; }
145 return $$pack;
148 sub align($) {
149 my $self = shift;
151 my $align = \${$self->{ALIGN}};
153 $self->_refresh();
155 return $$align;
158 sub fields($) {
159 my $self = shift;
161 my $count = $self->field_count;
163 my @fields = ();
164 for (my $n = 0; $n < $count; $n++) {
165 my $field = 'c_type_field'->new($self, $n);
166 push @fields, $field;
168 return @fields;
171 sub field_base_sizes($) {
172 my $self = shift;
173 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
175 $self->_refresh();
177 return $$field_base_sizes;
180 sub field_aligns($) {
181 my $self = shift;
182 my $field_aligns = \${$self->{FIELD_ALIGNS}};
184 $self->_refresh();
186 return $$field_aligns;
189 sub field_count($) {
190 my $self = shift;
191 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
193 my @field_type_names = @{$$field_type_names};
194 my $count = scalar(@field_type_names);
196 return $count;
199 sub field_names($;$)
201 my $self = shift;
202 my $field_names = \${$self->{FIELD_NAMES}};
203 my $dirty = \${$self->{DIRTY}};
205 local $_ = shift;
207 if(defined($_)) { $$field_names = $_; $$dirty = 1; }
209 return $$field_names;
212 sub field_offsets($) {
213 my $self = shift;
214 my $field_offsets = \${$self->{FIELD_OFFSETS}};
216 $self->_refresh();
218 return $$field_offsets;
221 sub field_sizes($) {
222 my $self = shift;
223 my $field_sizes = \${$self->{FIELD_SIZES}};
225 $self->_refresh();
227 return $$field_sizes;
230 sub field_type_names($;$)
232 my $self = shift;
233 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
234 my $dirty = \${$self->{DIRTY}};
236 local $_ = shift;
238 if(defined($_)) { $$field_type_names = $_; $$dirty = 1; }
240 return $$field_type_names;
243 sub size($) {
244 my $self = shift;
246 my $size = \${$self->{SIZE}};
248 $self->_refresh();
250 return $$size;
253 sub _refresh($) {
254 my $self = shift;
256 my $dirty = \${$self->{DIRTY}};
258 return if !$$dirty;
260 my $find_align = \${$self->{FIND_ALIGN}};
261 my $find_kind = \${$self->{FIND_KIND}};
262 my $find_size = \${$self->{FIND_SIZE}};
263 my $find_count = \${$self->{FIND_COUNT}};
265 my $align = \${$self->{ALIGN}};
266 my $kind = \${$self->{KIND}};
267 my $size = \${$self->{SIZE}};
268 my $field_aligns = \${$self->{FIELD_ALIGNS}};
269 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
270 my $field_offsets = \${$self->{FIELD_OFFSETS}};
271 my $field_sizes = \${$self->{FIELD_SIZES}};
273 my $pack = $self->pack;
274 $pack = 8 if !defined($pack);
276 my $max_field_align = 0;
278 my $offset = 0;
279 my $bitfield_size = 0;
280 my $bitfield_bits = 0;
282 my $n = 0;
283 foreach my $field ($self->fields) {
284 my $type_name = $field->type_name;
286 my $bits;
287 my $count;
288 if ($type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/)
290 $count = $2;
291 $bits = $3;
293 my $declspec_align;
294 if ($type_name =~ s/\s+DECLSPEC_ALIGN\((\d+)\)//)
296 $declspec_align=$1;
298 my $base_size = &$$find_size($type_name);
299 my $type_size=$base_size;
300 if (defined $count)
302 $count=&$$find_count($count) if ($count !~ /^\d+$/);
303 if (!defined $count)
305 $type_size=undef;
307 else
309 $type_size *= int($count);
312 if ($bitfield_size != 0)
314 if (($type_name eq "" and defined $bits and $bits == 0) or
315 (defined $type_size and $bitfield_size != $type_size) or
316 !defined $bits or
317 $bitfield_bits + $bits > 8 * $bitfield_size)
319 # This marks the end of the previous bitfield
320 $bitfield_size=0;
321 $bitfield_bits=0;
323 else
325 $bitfield_bits+=$bits;
326 $n++;
327 next;
331 $$align = &$$find_align($type_name);
332 $$align=$declspec_align if (defined $declspec_align);
334 if (defined $$align)
336 $$align = $pack if $$align > $pack;
337 $max_field_align = $$align if $$align > $max_field_align;
339 if ($offset % $$align != 0) {
340 $offset = (int($offset / $$align) + 1) * $$align;
344 if ($$kind !~ /^(?:struct|union)$/)
346 $$kind = &$$find_kind($type_name) || "";
349 if (!$type_size)
351 $$align = undef;
352 $$size = undef;
353 return;
356 $$$field_aligns[$n] = $$align;
357 $$$field_base_sizes[$n] = $base_size;
358 $$$field_offsets[$n] = $offset;
359 $$$field_sizes[$n] = $type_size;
360 $offset += $type_size;
362 if ($bits)
364 $bitfield_size=$type_size;
365 $bitfield_bits=$bits;
367 $n++;
370 $$align = $pack;
371 $$align = $max_field_align if $max_field_align < $pack;
373 $$size = $offset;
374 if ($$kind =~ /^(?:struct|union)$/) {
375 if ($$size % $$align != 0) {
376 $$size = (int($$size / $$align) + 1) * $$align;
380 $$dirty = 0;
383 package c_type_field;
385 sub new($$$) {
386 my $proto = shift;
387 my $class = ref($proto) || $proto;
388 my $self = {};
389 bless ($self, $class);
391 my $type = \${$self->{TYPE}};
392 my $number = \${$self->{NUMBER}};
394 $$type = shift;
395 $$number = shift;
397 return $self;
400 sub align($) {
401 my $self = shift;
402 my $type = \${$self->{TYPE}};
403 my $number = \${$self->{NUMBER}};
405 my $field_aligns = $$type->field_aligns;
407 return $$field_aligns[$$number];
410 sub base_size($) {
411 my $self = shift;
412 my $type = \${$self->{TYPE}};
413 my $number = \${$self->{NUMBER}};
415 my $field_base_sizes = $$type->field_base_sizes;
417 return $$field_base_sizes[$$number];
420 sub name($) {
421 my $self = shift;
422 my $type = \${$self->{TYPE}};
423 my $number = \${$self->{NUMBER}};
425 my $field_names = $$type->field_names;
427 return $$field_names[$$number];
430 sub offset($) {
431 my $self = shift;
432 my $type = \${$self->{TYPE}};
433 my $number = \${$self->{NUMBER}};
435 my $field_offsets = $$type->field_offsets;
437 return $$field_offsets[$$number];
440 sub size($) {
441 my $self = shift;
442 my $type = \${$self->{TYPE}};
443 my $number = \${$self->{NUMBER}};
445 my $field_sizes = $$type->field_sizes;
447 return $$field_sizes[$$number];
450 sub type_name($) {
451 my $self = shift;
452 my $type = \${$self->{TYPE}};
453 my $number = \${$self->{NUMBER}};
455 my $field_type_names = $$type->field_type_names;
457 return $$field_type_names[$$number];