Draw +/- correctly for large icon sizes.
[wine/hacks.git] / tools / winapi / c_type.pm
blobefe64c68ab8a332c930ce6f7045f6b0e2eb4a4ef
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
19 package c_type;
21 use strict;
23 use output qw($output);
25 sub new {
26 my $proto = shift;
27 my $class = ref($proto) || $proto;
28 my $self = {};
29 bless ($self, $class);
31 return $self;
34 ########################################################################
35 # set_find_align_callback
37 sub set_find_align_callback {
38 my $self = shift;
40 my $find_align = \${$self->{FIND_ALIGN}};
42 $$find_align = shift;
45 ########################################################################
46 # set_find_kind_callback
48 sub set_find_kind_callback {
49 my $self = shift;
51 my $find_kind = \${$self->{FIND_KIND}};
53 $$find_kind = shift;
56 ########################################################################
57 # set_find_size_callback
59 sub set_find_size_callback {
60 my $self = shift;
62 my $find_size = \${$self->{FIND_SIZE}};
64 $$find_size = shift;
67 ########################################################################
68 # set_find_count_callback
70 sub set_find_count_callback {
71 my $self = shift;
73 my $find_count = \${$self->{FIND_COUNT}};
75 $$find_count = shift;
78 sub kind {
79 my $self = shift;
80 my $kind = \${$self->{KIND}};
81 my $dirty = \${$self->{DIRTY}};
83 local $_ = shift;
85 if(defined($_)) { $$kind = $_; $$dirty = 1; }
87 if (!defined($$kind)) {
88 $self->_refresh();
91 return $$kind;
94 sub _name {
95 my $self = shift;
96 my $_name = \${$self->{_NAME}};
97 my $dirty = \${$self->{DIRTY}};
99 local $_ = shift;
101 if(defined($_)) { $$_name = $_; $$dirty = 1; }
103 return $$_name;
106 sub name {
107 my $self = shift;
108 my $name = \${$self->{NAME}};
109 my $dirty = \${$self->{DIRTY}};
111 local $_ = shift;
113 if(defined($_)) { $$name = $_; $$dirty = 1; }
115 if($$name) {
116 return $$name;
117 } else {
118 my $kind = \${$self->{KIND}};
119 my $_name = \${$self->{_NAME}};
121 return "$$kind $$_name";
125 sub pack {
126 my $self = shift;
127 my $pack = \${$self->{PACK}};
128 my $dirty = \${$self->{DIRTY}};
130 local $_ = shift;
132 if(defined($_)) { $$pack = $_; $$dirty = 1; }
134 return $$pack;
137 sub align {
138 my $self = shift;
140 my $align = \${$self->{ALIGN}};
142 $self->_refresh();
144 return $$align;
147 sub fields {
148 my $self = shift;
150 my $count = $self->field_count;
152 my @fields = ();
153 for (my $n = 0; $n < $count; $n++) {
154 my $field = 'c_type_field'->new($self, $n);
155 push @fields, $field;
157 return @fields;
160 sub field_base_sizes {
161 my $self = shift;
162 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
164 $self->_refresh();
166 return $$field_base_sizes;
169 sub field_aligns {
170 my $self = shift;
171 my $field_aligns = \${$self->{FIELD_ALIGNS}};
173 $self->_refresh();
175 return $$field_aligns;
178 sub field_count {
179 my $self = shift;
180 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
182 my @field_type_names = @{$$field_type_names};
183 my $count = scalar(@field_type_names);
185 return $count;
188 sub field_names {
189 my $self = shift;
190 my $field_names = \${$self->{FIELD_NAMES}};
191 my $dirty = \${$self->{DIRTY}};
193 local $_ = shift;
195 if(defined($_)) { $$field_names = $_; $$dirty = 1; }
197 return $$field_names;
200 sub field_offsets {
201 my $self = shift;
202 my $field_offsets = \${$self->{FIELD_OFFSETS}};
204 $self->_refresh();
206 return $$field_offsets;
209 sub field_sizes {
210 my $self = shift;
211 my $field_sizes = \${$self->{FIELD_SIZES}};
213 $self->_refresh();
215 return $$field_sizes;
218 sub field_type_names {
219 my $self = shift;
220 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
221 my $dirty = \${$self->{DIRTY}};
223 local $_ = shift;
225 if(defined($_)) { $$field_type_names = $_; $$dirty = 1; }
227 return $$field_type_names;
230 sub size {
231 my $self = shift;
233 my $size = \${$self->{SIZE}};
235 $self->_refresh();
237 return $$size;
240 sub _refresh {
241 my $self = shift;
243 my $dirty = \${$self->{DIRTY}};
245 return if !$$dirty;
247 my $find_align = \${$self->{FIND_ALIGN}};
248 my $find_kind = \${$self->{FIND_KIND}};
249 my $find_size = \${$self->{FIND_SIZE}};
250 my $find_count = \${$self->{FIND_COUNT}};
252 my $align = \${$self->{ALIGN}};
253 my $kind = \${$self->{KIND}};
254 my $size = \${$self->{SIZE}};
255 my $field_aligns = \${$self->{FIELD_ALIGNS}};
256 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
257 my $field_offsets = \${$self->{FIELD_OFFSETS}};
258 my $field_sizes = \${$self->{FIELD_SIZES}};
260 my $pack = $self->pack;
261 $pack = 8 if !defined($pack);
263 my $max_field_align = 0;
265 my $offset = 0;
266 my $bitfield_size = 0;
267 my $bitfield_bits = 0;
269 my $n = 0;
270 foreach my $field ($self->fields) {
271 my $type_name = $field->type_name;
273 my $bits;
274 my $count;
275 if ($type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/)
277 $count = $2;
278 $bits = $3;
280 my $declspec_align;
281 if ($type_name =~ s/\s+DECLSPEC_ALIGN\((\d+)\)//)
283 $declspec_align=$1;
285 my $base_size = &$$find_size($type_name);
286 my $type_size=$base_size;
287 if (defined $count)
289 $count=&$$find_count($count) if ($count !~ /^\d+$/);
290 if (!defined $count)
292 $type_size=undef;
294 else
296 $type_size *= int($count);
299 if ($bitfield_size != 0)
301 if (($type_name eq "" and defined $bits and $bits == 0) or
302 (defined $type_size and $bitfield_size != $type_size) or
303 !defined $bits or
304 $bitfield_bits + $bits > 8 * $bitfield_size)
306 # This marks the end of the previous bitfield
307 $bitfield_size=0;
308 $bitfield_bits=0;
310 else
312 $bitfield_bits+=$bits;
313 $n++;
314 next;
318 $$align = &$$find_align($type_name);
319 $$align=$declspec_align if (defined $declspec_align);
321 if (defined $$align)
323 $$align = $pack if $$align > $pack;
324 $max_field_align = $$align if $$align > $max_field_align;
326 if ($offset % $$align != 0) {
327 $offset = (int($offset / $$align) + 1) * $$align;
331 if ($$kind !~ /^(?:struct|union)$/)
333 $$kind = &$$find_kind($type_name) || "";
336 if (!$type_size)
338 $$align = undef;
339 $$size = undef;
340 return;
343 $$$field_aligns[$n] = $$align;
344 $$$field_base_sizes[$n] = $base_size;
345 $$$field_offsets[$n] = $offset;
346 $$$field_sizes[$n] = $type_size;
347 $offset += $type_size;
349 if ($bits)
351 $bitfield_size=$type_size;
352 $bitfield_bits=$bits;
354 $n++;
357 $$align = $pack;
358 $$align = $max_field_align if $max_field_align < $pack;
360 $$size = $offset;
361 if ($$kind =~ /^(?:struct|union)$/) {
362 if ($$size % $$align != 0) {
363 $$size = (int($$size / $$align) + 1) * $$align;
367 $$dirty = 0;
370 package c_type_field;
372 sub new {
373 my $proto = shift;
374 my $class = ref($proto) || $proto;
375 my $self = {};
376 bless ($self, $class);
378 my $type = \${$self->{TYPE}};
379 my $number = \${$self->{NUMBER}};
381 $$type = shift;
382 $$number = shift;
384 return $self;
387 sub align {
388 my $self = shift;
389 my $type = \${$self->{TYPE}};
390 my $number = \${$self->{NUMBER}};
392 my $field_aligns = $$type->field_aligns;
394 return $$field_aligns[$$number];
397 sub base_size {
398 my $self = shift;
399 my $type = \${$self->{TYPE}};
400 my $number = \${$self->{NUMBER}};
402 my $field_base_sizes = $$type->field_base_sizes;
404 return $$field_base_sizes[$$number];
407 sub name {
408 my $self = shift;
409 my $type = \${$self->{TYPE}};
410 my $number = \${$self->{NUMBER}};
412 my $field_names = $$type->field_names;
414 return $$field_names[$$number];
417 sub offset {
418 my $self = shift;
419 my $type = \${$self->{TYPE}};
420 my $number = \${$self->{NUMBER}};
422 my $field_offsets = $$type->field_offsets;
424 return $$field_offsets[$$number];
427 sub size {
428 my $self = shift;
429 my $type = \${$self->{TYPE}};
430 my $number = \${$self->{NUMBER}};
432 my $field_sizes = $$type->field_sizes;
434 return $$field_sizes[$$number];
437 sub type_name {
438 my $self = shift;
439 my $type = \${$self->{TYPE}};
440 my $number = \${$self->{NUMBER}};
442 my $field_type_names = $$type->field_type_names;
444 return $$field_type_names[$$number];