Remove the winetest_ok() hack that adds a trailing '\n' if it is
[wine.git] / tools / winapi / c_type.pm
blob322c62170a90b15d7e6990c4010d673ece890cb4
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 sub kind {
68 my $self = shift;
69 my $kind = \${$self->{KIND}};
70 my $dirty = \${$self->{DIRTY}};
72 local $_ = shift;
74 if(defined($_)) { $$kind = $_; $$dirty = 1; }
76 if (!defined($$kind)) {
77 $self->_refresh();
80 return $$kind;
83 sub _name {
84 my $self = shift;
85 my $_name = \${$self->{_NAME}};
86 my $dirty = \${$self->{DIRTY}};
88 local $_ = shift;
90 if(defined($_)) { $$_name = $_; $$dirty = 1; }
92 return $$_name;
95 sub name {
96 my $self = shift;
97 my $name = \${$self->{NAME}};
98 my $dirty = \${$self->{DIRTY}};
100 local $_ = shift;
102 if(defined($_)) { $$name = $_; $$dirty = 1; }
104 if($$name) {
105 return $$name;
106 } else {
107 my $kind = \${$self->{KIND}};
108 my $_name = \${$self->{_NAME}};
110 return "$$kind $$_name";
114 sub pack {
115 my $self = shift;
116 my $pack = \${$self->{PACK}};
117 my $dirty = \${$self->{DIRTY}};
119 local $_ = shift;
121 if(defined($_)) { $$pack = $_; $$dirty = 1; }
123 return $$pack;
126 sub align {
127 my $self = shift;
129 my $align = \${$self->{ALIGN}};
131 $self->_refresh();
133 return $$align;
136 sub fields {
137 my $self = shift;
139 my $count = $self->field_count;
141 my @fields = ();
142 for (my $n = 0; $n < $count; $n++) {
143 my $field = 'c_type_field'->new($self, $n);
144 push @fields, $field;
146 return @fields;
149 sub field_base_sizes {
150 my $self = shift;
151 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
153 $self->_refresh();
155 return $$field_base_sizes;
158 sub field_aligns {
159 my $self = shift;
160 my $field_aligns = \${$self->{FIELD_ALIGNS}};
162 $self->_refresh();
164 return $$field_aligns;
167 sub field_count {
168 my $self = shift;
169 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
171 my @field_type_names = @{$$field_type_names};
172 my $count = scalar(@field_type_names);
174 return $count;
177 sub field_names {
178 my $self = shift;
179 my $field_names = \${$self->{FIELD_NAMES}};
180 my $dirty = \${$self->{DIRTY}};
182 local $_ = shift;
184 if(defined($_)) { $$field_names = $_; $$dirty = 1; }
186 return $$field_names;
189 sub field_offsets {
190 my $self = shift;
191 my $field_offsets = \${$self->{FIELD_OFFSETS}};
193 $self->_refresh();
195 return $$field_offsets;
198 sub field_sizes {
199 my $self = shift;
200 my $field_sizes = \${$self->{FIELD_SIZES}};
202 $self->_refresh();
204 return $$field_sizes;
207 sub field_type_names {
208 my $self = shift;
209 my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
210 my $dirty = \${$self->{DIRTY}};
212 local $_ = shift;
214 if(defined($_)) { $$field_type_names = $_; $$dirty = 1; }
216 return $$field_type_names;
219 sub size {
220 my $self = shift;
222 my $size = \${$self->{SIZE}};
224 $self->_refresh();
226 return $$size;
229 sub _refresh {
230 my $self = shift;
232 my $dirty = \${$self->{DIRTY}};
234 return if !$$dirty;
236 my $find_align = \${$self->{FIND_ALIGN}};
237 my $find_kind = \${$self->{FIND_KIND}};
238 my $find_size = \${$self->{FIND_SIZE}};
240 my $align = \${$self->{ALIGN}};
241 my $kind = \${$self->{KIND}};
242 my $size = \${$self->{SIZE}};
243 my $field_aligns = \${$self->{FIELD_ALIGNS}};
244 my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
245 my $field_offsets = \${$self->{FIELD_OFFSETS}};
246 my $field_sizes = \${$self->{FIELD_SIZES}};
248 my $pack = $self->pack;
249 $pack = 4 if !defined($pack);
251 my $max_field_align = 0;
253 my $offset = 0;
254 my $offset_bits = 0;
256 my $n = 0;
257 foreach my $field ($self->fields) {
258 my $type_name = $field->type_name;
259 my $type_size = &$$find_size($type_name);
261 my $base_type_name = $type_name;
262 if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) {
263 my $count = $2;
264 my $bits = $3;
266 my $base_size = &$$find_size($base_type_name);
267 $$align = &$$find_align($base_type_name);
269 if (defined($$align)) {
270 $$align = $pack if $$align > $pack;
271 $max_field_align = $$align if $$align > $max_field_align;
273 if ($offset % $$align != 0) {
274 $offset = (int($offset / $$align) + 1) * $$align;
278 if ($$kind !~ /^(?:struct|union)$/) {
279 $$kind = &$$find_kind($type_name) || "";
282 if (!defined($type_size)) {
283 $$align = undef;
284 $$size = undef;
285 return;
286 } elsif ($type_size >= 0) {
287 if ($offset_bits) {
288 $offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack));
289 $offset_bits = 0;
292 $$$field_aligns[$n] = $$align;
293 $$$field_base_sizes[$n] = $base_size;
294 $$$field_offsets[$n] = $offset;
295 $$$field_sizes[$n] = $type_size;
297 $offset += $type_size;
298 } else {
299 $$$field_aligns[$n] = $$align;
300 $$$field_base_sizes[$n] = $base_size;
301 $$$field_offsets[$n] = $offset;
302 $$$field_sizes[$n] = $type_size;
304 $offset_bits += -$type_size;
307 $n++;
310 $$align = $pack;
311 $$align = $max_field_align if $max_field_align < $pack;
313 if ($offset_bits) {
314 $offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack));
315 $offset_bits = 0;
318 $$size = $offset;
319 if ($$kind =~ /^(?:struct|union)$/) {
320 if ($$size % $$align != 0) {
321 $$size = (int($$size / $$align) + 1) * $$align;
325 $$dirty = 0;
328 package c_type_field;
330 sub new {
331 my $proto = shift;
332 my $class = ref($proto) || $proto;
333 my $self = {};
334 bless ($self, $class);
336 my $type = \${$self->{TYPE}};
337 my $number = \${$self->{NUMBER}};
339 $$type = shift;
340 $$number = shift;
342 return $self;
345 sub align {
346 my $self = shift;
347 my $type = \${$self->{TYPE}};
348 my $number = \${$self->{NUMBER}};
350 my $field_aligns = $$type->field_aligns;
352 return $$field_aligns[$$number];
355 sub base_size {
356 my $self = shift;
357 my $type = \${$self->{TYPE}};
358 my $number = \${$self->{NUMBER}};
360 my $field_base_sizes = $$type->field_base_sizes;
362 return $$field_base_sizes[$$number];
365 sub name {
366 my $self = shift;
367 my $type = \${$self->{TYPE}};
368 my $number = \${$self->{NUMBER}};
370 my $field_names = $$type->field_names;
372 return $$field_names[$$number];
375 sub offset {
376 my $self = shift;
377 my $type = \${$self->{TYPE}};
378 my $number = \${$self->{NUMBER}};
380 my $field_offsets = $$type->field_offsets;
382 return $$field_offsets[$$number];
385 sub size {
386 my $self = shift;
387 my $type = \${$self->{TYPE}};
388 my $number = \${$self->{NUMBER}};
390 my $field_sizes = $$type->field_sizes;
392 return $$field_sizes[$$number];
395 sub type_name {
396 my $self = shift;
397 my $type = \${$self->{TYPE}};
398 my $number = \${$self->{NUMBER}};
400 my $field_type_names = $$type->field_type_names;
402 return $$field_type_names[$$number];