msvfw32: Correctly store internal pointer.
[wine.git] / tools / winapi / c_type.pm
blobba1aec26438357a1af8e3996619e516843e33301
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;
22 use warnings 'all';
24 use output qw($output);
26 sub _refresh($);
28 sub new($)
30 my ($proto) = @_;
31 my $class = ref($proto) || $proto;
32 my $self = {};
33 bless $self, $class;
35 return $self;
39 # Callback setters
42 sub set_find_align_callback($$)
44 my ($self, $find_align) = @_;
45 $self->{FIND_ALIGN} = $find_align;
48 sub set_find_kind_callback($$)
50 my ($self, $find_kind) = @_;
51 $self->{FIND_KIND} = $find_kind;
54 sub set_find_size_callback($$)
56 my ($self, $find_size) = @_;
57 $self->{FIND_SIZE} = $find_size;
60 sub set_find_count_callback($$)
62 my ($self, $find_count) = @_;
63 $self->{FIND_COUNT} = $find_count;
68 # Property setter / getter functions (each does both)
71 sub kind($;$)
73 my ($self, $kind) = @_;
74 if (defined $kind)
76 $self->{KIND} = $kind;
77 $self->{DIRTY} = 1;
79 $self->_refresh() if (!defined $self->{KIND});
80 return $self->{KIND};
83 sub _name($;$)
85 my ($self, $_name) = @_;
86 if (defined $_name)
88 $self->{_NAME} = $_name;
89 $self->{DIRTY} = 1;
91 return $self->{_NAME};
94 sub name($;$)
96 my ($self, $name) = @_;
97 if (defined $name)
99 $self->{NAME} = $name;
100 $self->{DIRTY} = 1;
102 return $self->{NAME} if ($self->{NAME});
103 return "$self->{KIND} $self->{_NAME}";
106 sub pack($;$)
108 my ($self, $pack) = @_;
109 if (defined $pack)
111 $self->{PACK} = $pack;
112 $self->{DIRTY} = 1;
114 return $self->{PACK};
117 sub align($)
119 my ($self) = @_;
120 $self->_refresh();
121 return $self->{ALIGN};
124 sub fields($)
126 my ($self) = @_;
128 my $count = $self->field_count;
130 my @fields = ();
131 for (my $n = 0; $n < $count; $n++) {
132 my $field = 'c_type_field'->new($self, $n);
133 push @fields, $field;
135 return @fields;
138 sub field_base_sizes($)
140 my ($self) = @_;
141 $self->_refresh();
142 return $self->{FIELD_BASE_SIZES};
145 sub field_aligns($)
147 my ($self) = @_;
148 $self->_refresh();
149 return $self->{FIELD_ALIGNS};
152 sub field_count($)
154 my ($self) = @_;
155 return scalar @{$self->{FIELD_TYPE_NAMES}};
158 sub field_names($;$)
160 my ($self, $field_names) = @_;
161 if (defined $field_names)
163 $self->{FIELD_NAMES} = $field_names;
164 $self->{DIRTY} = 1;
166 return $self->{FIELD_NAMES};
169 sub field_offsets($)
171 my ($self) = @_;
172 $self->_refresh();
173 return $self->{FIELD_OFFSETS};
176 sub field_sizes($)
178 my ($self) = @_;
179 $self->_refresh();
180 return $self->{FIELD_SIZES};
183 sub field_type_names($;$)
185 my ($self, $field_type_names) = @_;
186 if (defined $field_type_names)
188 $self->{FIELD_TYPE_NAMES} = $field_type_names;
189 $self->{DIRTY} = 1;
191 return $self->{FIELD_TYPE_NAMES};
194 sub size($)
196 my ($self) = @_;
197 $self->_refresh();
198 return $self->{SIZE};
201 sub _refresh($)
203 my ($self) = @_;
204 return if (!$self->{DIRTY});
206 my $pack = $self->pack;
207 $pack = 8 if !defined($pack);
209 my $max_field_align = 0;
211 my $offset = 0;
212 my $bitfield_size = 0;
213 my $bitfield_bits = 0;
215 my $n = 0;
216 foreach my $field ($self->fields())
218 my $type_name = $field->type_name;
220 my $bits;
221 my $count;
222 if ($type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/)
224 $count = $2;
225 $bits = $3;
227 my $declspec_align;
228 if ($type_name =~ s/\s+DECLSPEC_ALIGN\((\d+)\)//)
230 $declspec_align=$1;
232 my $base_size = $self->{FIND_SIZE}($type_name);
233 my $type_size=$base_size;
234 if (defined $count)
236 $count=$self->{FIND_COUNT}($count) if ($count !~ /^\d+$/);
237 if (!defined $count)
239 $type_size=undef;
241 else
243 if (!defined $type_size)
245 print STDERR "$type_name -> type_size=undef, count=$count\n";
247 else
249 $type_size *= int($count);
253 if ($bitfield_size != 0)
255 if (($type_name eq "" and defined $bits and $bits == 0) or
256 (defined $type_size and $bitfield_size != $type_size) or
257 !defined $bits or
258 $bitfield_bits + $bits > 8 * $bitfield_size)
260 # This marks the end of the previous bitfield
261 $bitfield_size=0;
262 $bitfield_bits=0;
264 else
266 $bitfield_bits+=$bits;
267 $n++;
268 next;
272 $self->{ALIGN} = $self->{FIND_ALIGN}($type_name);
273 $self->{ALIGN} = $declspec_align if (defined $declspec_align);
275 if (defined $self->{ALIGN})
277 $self->{ALIGN} = $pack if ($self->{ALIGN} > $pack);
278 $max_field_align = $self->{ALIGN} if ($self->{ALIGN}) > $max_field_align;
280 if ($offset % $self->{ALIGN} != 0) {
281 $offset = (int($offset / $self->{ALIGN}) + 1) * $self->{ALIGN};
285 if ($self->{KIND} !~ /^(?:struct|union)$/)
287 $self->{KIND} = $self->{FIND_KIND}($type_name) || "";
290 if (!$type_size)
292 $self->{ALIGN} = undef;
293 $self->{SIZE} = undef;
294 return;
297 $self->{FIELD_ALIGNS}->[$n] = $self->{ALIGN};
298 $self->{FIELD_BASE_SIZES}->[$n] = $base_size;
299 $self->{FIELD_OFFSETS}->[$n] = $offset;
300 $self->{FIELD_SIZES}->[$n] = $type_size;
301 $offset += $type_size;
303 if ($bits)
305 $bitfield_size=$type_size;
306 $bitfield_bits=$bits;
308 $n++;
311 $self->{ALIGN} = $pack;
312 $self->{ALIGN} = $max_field_align if ($max_field_align < $pack);
314 $self->{SIZE} = $offset;
315 if ($self->{KIND} =~ /^(?:struct|union)$/) {
316 if ($self->{SIZE} % $self->{ALIGN} != 0) {
317 $self->{SIZE} = (int($self->{SIZE} / $self->{ALIGN}) + 1) * $self->{ALIGN};
321 $self->{DIRTY} = 0;
324 package c_type_field;
326 sub new($$$)
328 my ($proto, $type, $number) = @_;
329 my $class = ref($proto) || $proto;
330 my $self = {TYPE=> $type,
331 NUMBER => $number
333 bless $self, $class;
334 return $self;
337 sub align($)
339 my ($self) = @_;
340 return undef unless defined $self->{TYPE}->field_aligns();
341 return $self->{TYPE}->field_aligns()->[$self->{NUMBER}];
344 sub base_size($)
346 my ($self) = @_;
347 return undef unless defined $self->{TYPE}->field_base_sizes();
348 return $self->{TYPE}->field_base_sizes()->[$self->{NUMBER}];
351 sub name($)
353 my ($self) = @_;
354 return undef unless defined $self->{TYPE}->field_names();
355 return $self->{TYPE}->field_names()->[$self->{NUMBER}];
358 sub offset($)
360 my ($self) = @_;
361 return undef unless defined $self->{TYPE}->field_offsets();
362 return $self->{TYPE}->field_offsets()->[$self->{NUMBER}];
365 sub size($)
367 my ($self) = @_;
368 return undef unless defined $self->{TYPE}->field_sizes();
369 return $self->{TYPE}->field_sizes()->[$self->{NUMBER}];
372 sub type_name($)
374 my ($self) = @_;
375 return $self->{TYPE}->field_type_names()->[$self->{NUMBER}];