*** winapi_test * tools/winapi/c_parser.pm, tools/winapi/c_type.pm, tools/winapi/tests.dat, tools/winapi/winapi_extract, tools/winapi/winapi_test: Reorganized the code for better support of data structures parsing. Index: wine/tools/winapi/c_parser.pm =================================================================== RCS file: /home/wine/wine/tools/winapi/c_parser.pm,v retrieving revision 1.7 diff -u -u -r1.7 c_parser.pm --- wine/tools/winapi/c_parser.pm 1 Oct 2002 18:10:54 -0000 1.7 +++ wine/tools/winapi/c_parser.pm 7 Oct 2002 18:32:39 -0000 @@ -1112,8 +1112,8 @@ my $match; while($self->_parse_c('(?:const|inline|extern(?:\s+\"C\")?|EXTERN_C|static|v olatile|' . - 'signed(?=\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b)|' . - 'unsigned(?=\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b)|' . + 'signed(?=\s+__int64\b|\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b)| ' . + 'unsigned(?=\s+__int64\b|\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b )|' . 'long(?=\s+double\b|\s+int\b|\s+long\b))(?=\b)', \$_, \$line, \$column, \$match)) { @@ -1654,22 +1654,22 @@ if ($kind =~ /^struct|union$/) { my $name = ""; - my @field_types = (); + my @field_type_names = (); my @field_names = (); my $match; - while ($self->_parse_c_on_same_level_until_one_of(';', \$_, \$line, \$column, \$match)) + while ($_ && $self->_parse_c_on_same_level_until_one_of(';', \$_, \$line, \$column, \$match)) { my $field_linkage; - my $field_type; + my $field_type_name; my $field_name; - if ($self->parse_c_variable(\$match, \$line, \$column, \$field_linkage, \$field_type, \$field_name)) { - $field_type =~ s/\s+/ /g; + if ($self->parse_c_variable(\$match, \$line, \$column, \$field_linkage, \$field_type_name, \$field_name)) { + $field_type_name =~ s/\s+/ /g; - push @field_types, $field_type; + push @field_type_names, $field_type_name; push @field_names, $field_name; - # $output->write("$kind:$_name:$field_type:$field_name\n"); + # $output->write("$kind:$_name:$field_type_name:$field_name\n"); } elsif ($match) { $self->_parse_c_error($_, $line, $column, "typedef $kind: '$match'"); } @@ -1708,7 +1708,7 @@ $type->kind($kind); $type->_name($_name); $type->name($name); - $type->field_types([@field_types]); + $type->field_type_names([@field_type_names]); $type->field_names([@field_names]); &$$found_type($type); @@ -1759,9 +1759,43 @@ # FIXME: Not correct # $output->write("typedef:$name:$_name\n"); } - } elsif ($self->_parse_c("typedef", \$_, \$line, \$column)) { - # Nothing + my $linkage; + my $type_name; + my $name; + + if ($self->parse_c_variable(\$_, \$line, \$column, \$linkage, \$type_name, \$name)) { + $type_name =~ s/\s+/ /g; + + if(defined($type_name) && defined($name)) { + my $type = &$$create_type(); + + if (length($name) == 0) { + $self->_parse_c_error($_, $line, $column, "typedef"); + } + + $type->kind(""); + $type->name($name); + $type->pack(1); + $type->field_type_names([$type_name]); + $type->field_names([""]); + + &$$found_type($type); + } + + if (0 && $_ && !/^,/) { + $self->_parse_c_error($_, $line, $column, "typedef"); + } + } else { + $self->_parse_c_error($_, $line, $column, "typedef"); + } + } elsif (0 && $self->_parse_c("typedef", \$_, \$line, \$column)) { + my $type_name; + $self->_parse_c('\w+', \$_, \$line, \$column, \$type_name); + + my $name; + $self->_parse_c('\w+', \$_, \$line, \$column, \$name); + } else { return 0; } @@ -1808,8 +1842,8 @@ my $match; while($self->_parse_c('(?:const|inline|extern(?:\s+\"C\")?|EXTERN_C|static|v olatile|' . - 'signed(?=\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b)|' . - 'unsigned(?=\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b)|' . + 'signed(?=\s+__int64\b|\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b)| ' . + 'unsigned(?=\s+__int64\b|\s+char\b|\s+int\b|\s+long(?:\s+long)?\b|\s+short\b )|' . 'long(?=\s+double\b|\s+int\b|\s+long\b))(?=\b)', \$_, \$line, \$column, \$match)) { @@ -1824,6 +1858,8 @@ if($finished) { # Nothing + } elsif(/^$/) { + return 0; } elsif(s/^(enum|struct|union)(?:\s+(\w+))?\s*\{//s) { my $kind = $1; my $_name = $2; @@ -1865,6 +1901,8 @@ $name = $2; $finished = 1; + } else { + $self->_parse_c_warning($_, $line, $column, "variable", "'$_'"); } if($finished) { Index: wine/tools/winapi/c_type.pm =================================================================== RCS file: /home/wine/wine/tools/winapi/c_type.pm,v retrieving revision 1.3 diff -u -u -r1.3 c_type.pm --- wine/tools/winapi/c_type.pm 2 Oct 2002 19:54:14 -0000 1.3 +++ wine/tools/winapi/c_type.pm 7 Oct 2002 18:32:40 -0000 @@ -20,6 +20,8 @@ use strict; +use output qw($output); + sub new { my $proto = shift; my $class = ref($proto) || $proto; @@ -83,18 +85,45 @@ sub fields { my $self = shift; - my @field_types = @{$self->field_types}; - my @field_names = @{$self->field_names}; + my $find_size = shift; + + if (defined($find_size)) { + $self->_refresh($find_size); + } + + my $count = $self->field_count; - my $count = scalar(@field_types); - my @fields = (); for (my $n = 0; $n < $count; $n++) { - push @fields, [$field_types[$n], $field_names[$n]]; + my $field = 'c_type_field'->new($self, $n); + push @fields, $field; } return @fields; } +sub field_aligns { + my $self = shift; + my $field_aligns = \${$self->{FIELD_ALIGNS}}; + + my $find_size = shift; + + if (defined($find_size)) { + $self->_refresh($find_size); + } + + return $$field_aligns; +} + +sub field_count { + my $self = shift; + my $field_type_names = \${$self->{FIELD_TYPE_NAMES}}; + + my @field_type_names = @{$$field_type_names}; + my $count = scalar(@field_type_names); + + return $count; +} + sub field_names { my $self = shift; my $field_names = \${$self->{FIELD_NAMES}}; @@ -106,15 +135,186 @@ return $$field_names; } -sub field_types { +sub field_offsets { my $self = shift; - my $field_types = \${$self->{FIELD_TYPES}}; + my $field_offsets = \${$self->{FIELD_OFFSETS}}; + + my $find_size = shift; + + if (defined($find_size)) { + $self->_refresh($find_size); + } + + return $$field_offsets; +} + +sub field_sizes { + my $self = shift; + my $field_sizes = \${$self->{FIELD_SIZES}}; + + my $find_size = shift; + + if (defined($find_size)) { + $self->_refresh($find_size); + } + + return $$field_sizes; +} + +sub field_type_names { + my $self = shift; + my $field_type_names = \${$self->{FIELD_TYPE_NAMES}}; local $_ = shift; - if(defined($_)) { $$field_types = $_; } + if(defined($_)) { $$field_type_names = $_; } + + return $$field_type_names; +} + +sub size { + my $self = shift; + + my $size = \${$self->{SIZE}}; + + my $find_size = shift; + if (defined($find_size)) { + $self->_refresh($find_size); + } + + return $$size; +} + +sub _refresh { + my $self = shift; + + my $field_aligns = \${$self->{FIELD_ALIGNS}}; + my $field_offsets = \${$self->{FIELD_OFFSETS}}; + my $field_sizes = \${$self->{FIELD_SIZES}}; + my $size = \${$self->{SIZE}}; + + my $find_size = shift; + + my $pack = $self->pack; + + my $offset = 0; + my $offset_bits = 0; + + my $n = 0; + foreach my $field ($self->fields) { + my $type_name = $field->type_name; + my $size = &$find_size($type_name); + + + my $base_type_name = $type_name; + if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) { + my $count = $2; + my $bits = $3; + } + my $base_size = &$find_size($base_type_name); + + my $align = 0; + $align = $base_size % 4 if defined($base_size); + $align = 4 if !$align; + + if (!defined($size)) { + $$size = undef; + return; + } elsif ($size >= 0) { + if ($offset_bits) { + $offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack)); + $offset_bits = 0; + } + + $$$field_aligns[$n] = $align; + $$$field_offsets[$n] = $offset; + $$$field_sizes[$n] = $size; + + $offset += $size; + } else { + $$$field_aligns[$n] = $align; + $$$field_offsets[$n] = $offset; + $$$field_sizes[$n] = $size; + + $offset_bits += -$size; + } + + $n++; + } + + $$size = $offset; + if (1) { + if ($$size % $pack != 0) { + $$size = (int($$size / $pack) + 1) * $pack; + } + } +} + +package c_type_field; + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = {}; + bless ($self, $class); + + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + $$type = shift; + $$number = shift; + + return $self; +} + +sub align { + my $self = shift; + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + my $field_aligns = $$type->field_aligns; + + return $$field_aligns[$$number]; +} + +sub name { + my $self = shift; + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + my $field_names = $$type->field_names; + + return $$field_names[$$number]; +} + +sub offset { + my $self = shift; + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + my $field_offsets = $$type->field_offsets; + + return $$field_offsets[$$number]; +} + +sub size { + my $self = shift; + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + my $field_sizes = $$type->field_sizes; + + return $$field_sizes[$$number]; +} + +sub type_name { + my $self = shift; + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + my $field_type_names = $$type->field_type_names; - return $$field_types; + return $$field_type_names[$$number]; } 1; Index: wine/tools/winapi/tests.dat =================================================================== RCS file: /home/wine/wine/tools/winapi/tests.dat,v retrieving revision 1.2 diff -u -u -r1.2 tests.dat --- wine/tools/winapi/tests.dat 2 Oct 2002 19:54:14 -0000 1.2 +++ wine/tools/winapi/tests.dat 7 Oct 2002 18:32:40 -0000 @@ -8,6 +8,9 @@ %include +basetsd.h +winnt.h +windef.h winbase.h %struct @@ -25,11 +28,11 @@ EXIT_PROCESS_DEBUG_INFO EXIT_THREAD_DEBUG_INFO # FILETIME -# HW_PROFILE_INFOA -LDT_ENTRY +HW_PROFILE_INFOA +# LDT_ENTRY LOAD_DLL_DEBUG_INFO MEMORYSTATUS -# OFSTRUCT +OFSTRUCT OSVERSIONINFOA OSVERSIONINFOEXA OSVERSIONINFOEXW @@ -44,7 +47,7 @@ STARTUPINFOW SYSLEVEL SYSTEMTIME -SYSTEM_INFO +# SYSTEM_INFO SYSTEM_POWER_STATUS TIME_ZONE_INFORMATION UNLOAD_DLL_DEBUG_INFO @@ -63,6 +66,9 @@ %include +basetsd.h +winnt.h +windef.h wingdi.h %struct @@ -71,20 +77,20 @@ ABCFLOAT BITMAP BITMAPCOREHEADER -# BITMAPCOREINFO +BITMAPCOREINFO BITMAPFILEHEADER -# BITMAPINFO +BITMAPINFO BITMAPINFOHEADER -# BITMAPV4HEADER -# BITMAPV5HEADER +BITMAPV4HEADER +BITMAPV5HEADER BLENDFUNCTION -# CHARSETINFO +CHARSETINFO CIEXYZ -# CIEXYZTRIPLE -# COLORADJUSTMENT +CIEXYZTRIPLE +COLORADJUSTMENT # DEVMODEA # DEVMODEW -# DIBSECTION +DIBSECTION DISPLAY_DEVICEA DISPLAY_DEVICEW DOCINFOA @@ -94,23 +100,23 @@ EMRANGLEARC EMRARC EMRBITBLT -# EMRCREATEBRUSHINDIRECT -# EMRCREATECOLORSPACE +EMRCREATEBRUSHINDIRECT +EMRCREATECOLORSPACE # EMRCREATECOLORSPACEW EMRCREATEDIBPATTERNBRUSHPT EMRCREATEMONOBRUSH -# EMRCREATEPALETTE -# EMRCREATEPEN +EMRCREATEPALETTE +EMRCREATEPEN EMRDELETECOLORSPACE EMRDELETEOBJECT EMRELLIPSE EMREOF EMREXCLUDECLIPRECT -# EMREXTCREATEFONTINDIRECTW -# EMREXTCREATEPEN +EMREXTCREATEFONTINDIRECTW +EMREXTCREATEPEN EMREXTFLOODFILL # EMREXTSELECTCLIPRGN -# EMREXTTEXTOUTA +EMREXTTEXTOUTA EMRFILLPATH # EMRFILLRGN EMRFORMAT @@ -123,12 +129,12 @@ EMRMASKBLT EMRMODIFYWORLDTRANSFORM EMROFFSETCLIPRGN -# EMRPIXELFORMAT +EMRPIXELFORMAT EMRPLGBLT # EMRPOLYDRAW EMRPOLYLINE EMRPOLYPOLYLINE -# EMRPOLYTEXTOUTA +EMRPOLYTEXTOUTA EMRRESIZEPALETTE EMRRESTOREDC EMRROUNDRECT @@ -138,7 +144,7 @@ EMRSETARCDIRECTION EMRSETBKCOLOR EMRSETBRUSHORGEX -# EMRSETCOLORADJUSTMENT +EMRSETCOLORADJUSTMENT EMRSETDIBITSTODEIVCE EMRSETMAPPERFLAGS EMRSETMITERLIMIT @@ -150,30 +156,30 @@ EMRSTRETCHBLT EMRSTRETCHDIBITS EMRTEXT -# ENHMETAHEADER +ENHMETAHEADER ENHMETARECORD -# ENUMLOGFONTA -# ENUMLOGFONTEXA -# ENUMLOGFONTEXW -# ENUMLOGFONTW -# EXTLOGFONTA -# EXTLOGFONTW +ENUMLOGFONTA +ENUMLOGFONTEXA +ENUMLOGFONTEXW +ENUMLOGFONTW +EXTLOGFONTA +EXTLOGFONTW EXTLOGPEN -# FIXED +FIXED FONTSIGNATURE GCP_RESULTSA GCP_RESULTSW -# GLYPHMETRICS +GLYPHMETRICS GRADIENT_RECT GRADIENT_TRIANGLE HANDLETABLE KERNINGPAIR LOCALESIGNATURE LOGBRUSH -# LOGCOLORSPACEA -# LOGCOLORSPACEW -# LOGFONTA -# LOGFONTW +LOGCOLORSPACEA +LOGCOLORSPACEW +LOGFONTA +LOGFONTW LOGPALETTE LOGPEN MAT2 @@ -181,8 +187,8 @@ METAHEADER METARECORD # NEWTEXTMETRICA -# NEWTEXTMETRICEXA -# NEWTEXTMETRICEXW +NEWTEXTMETRICEXA +NEWTEXTMETRICEXW # NEWTEXTMETRICW # OUTLINETEXTMETRICA # OUTLINETEXTMETRICW @@ -191,18 +197,18 @@ PELARRAY PIXELFORMATDESCRIPTOR POINTFX -# POLYTEXTA -# POLYTEXTW +POLYTEXTA +POLYTEXTW # RASTERIZER_STATUS RGBQUAD # RGBTRIPLE # RGNDATA -# RGNDATAHEADER +RGNDATAHEADER TEXTMETRICA TEXTMETRICW -# TRIVERTEX -# TTPOLYCURVE -# TTPOLYGONHEADER +TRIVERTEX +TTPOLYCURVE +TTPOLYGONHEADER XFORM %%%dlls/user/tests @@ -215,6 +221,9 @@ %include +basetsd.h +winnt.h +windef.h winbase.h winuser.h Index: wine/tools/winapi/winapi_extract =================================================================== RCS file: /home/wine/wine/tools/winapi/winapi_extract,v retrieving revision 1.18 diff -u -u -r1.18 winapi_extract --- wine/tools/winapi/winapi_extract 1 Oct 2002 18:10:54 -0000 1.18 +++ wine/tools/winapi/winapi_extract 7 Oct 2002 18:32:40 -0000 @@ -328,13 +328,14 @@ my $name = $type->name; foreach my $field ($type->fields) { - (my $field_type, my $field_name) = @$field; + my $field_type_name = $field->type_name; + my $field_name = $field->name; if ($options->struct) { if ($name) { - $output->write("$name:$field_type:$field_name\n"); + $output->write("$name:$field_type_name:$field_name\n"); } else { - $output->write("$kind $_name:$field_type:$field_name\n"); + $output->write("$kind $_name:$field_type_name:$field_name\n"); } } } Index: wine/tools/winapi/winapi_test =================================================================== RCS file: /home/wine/wine/tools/winapi/winapi_test,v retrieving revision 1.2 diff -u -u -r1.2 winapi_test --- wine/tools/winapi/winapi_test 2 Oct 2002 19:54:14 -0000 1.2 +++ wine/tools/winapi/winapi_test 7 Oct 2002 18:32:40 -0000 @@ -49,7 +49,7 @@ my @files = (); { - my %files; + my %files; my %test_dirs; foreach my $test (@tests) { @@ -57,11 +57,23 @@ foreach my $test_dir (@test_dirs) { my @includes = $tests->get_section($test_dir, $test, "include"); foreach my $include (@includes) { - $files{"include/$include"}++; + $files{"include/$include"} = 1; + } + } + } + + foreach my $test (@tests) { + my @test_dirs = $tests->get_test_dirs($test); + foreach my $test_dir (@test_dirs) { + my @includes = $tests->get_section($test_dir, $test, "include"); + foreach my $include (@includes) { + if($files{"include/$include"}) { + push @files, "include/$include"; + $files{"include/$include"} = 0; + } } } } - @files = sort(keys(%files)); } my %file2types; @@ -70,6 +82,114 @@ my $progress_current = 0; my $progress_max = scalar(@files); +######################################################################## +# find_type + +my %type_name2type; + +my %defines = ( + "ANYSIZE_ARRAY" => 1, + "CCHDEVICENAME" => 32, + "ELF_VENDOR_SIZE" => 4, + "EXCEPTION_MAXIMUM_PARAMETERS" => 15, + "HW_PROFILE_GUIDLEN" => 39, + "IMAGE_NUMBEROF_DIRECTORY_ENTRIES" => 16, + "IMAGE_SIZEOF_SHORT_NAME" => 8, + "LF_FACESIZE" => 32, + "LF_FULLFACESIZE" => 64, + "MAXIMUM_SUPPORTED_EXTENSION" => 512, + "MAX_PATH" => 260, + "MAX_PROFILE_LEN" => 80, + "OFS_MAXPATHNAME" => 128, + "SIZE_OF_80387_REGISTERS" => 80, +); + +my %kludge_reported = ("FILETIME" => 1, "LARGE_INTEGER" => 1); +my %parse_reported; + +sub find_size { + my $type_name = shift; + + local $_ = $type_name; + + my $count; + my $bits; + if (s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) { + $count = $2; + $bits = $3; + } + + my $size; + if (0) { + # Nothing + } elsif (/\*+$/) { + $size = 4; + } elsif(/^(?:(?:signed\s+|unsigned\s+)?char)$/) { + $size = 1; + } elsif (/^(?:(?:signed\s+|unsigned\s+)?short)$/) { + $size = 2; + } elsif (/^(?:wchar_t)$/) { + $size = 2; + } elsif (/^(?:(?:signed\s+|unsigned\s+)?(?:__int32|int|long(?:\s+int)?)|unsigned|sig ned)$/) { + $size = 4; + } elsif (/^(?:float)$/) { + $size = 4; + } elsif (/^(?:signed\s+|unsigned\s+)?__int64$/) { + $size = 8; + } elsif (/^(?:double)$/) { + $size = 8; + } elsif (/^(?:long\s+double)$/) { + $size = 10; # ??? + } elsif (/^H(?:DC|BITMAP|BRUSH|ICON|INSTANCE|MENU|METAFILE|WND)$/) { + $size = 4; + } elsif (/^LP(?:CSTR|CWSTR|DWORD|STR|VOID|THREAD_START_ROUTINE|WSTR)$/) { + $size = 4; + } elsif (/^(?:(?:MSGBOX)CALLBACK[AW]?|(?:FAR|WND)PROC[AW]?)$/) { + $size = 4; + } elsif (/^(?:FILETIME|LARGE_INTEGER|LONGLONG)$/) { + $size = 8; + } elsif (/^(?:CRITICAL_SECTION)$/) { + $size = 24; + } elsif (/^(?:struct|union)$/) { + if (!$parse_reported{$_}) { + $output->write("$type_name: can't parse type\n"); + $parse_reported{$_} = 1; + } + $size = undef; + } else { + $size = undef; + } + + my $size2; + if (defined(my $type = $type_name2type{$_})) { + $size2 = $type->size; + } + + if (!defined($size)) { + $size = $size2; + } elsif (defined($size2) && !$kludge_reported{$_}) { + $kludge_reported{$_} = 1; + $output->write("$type_name: type needn't be kludged\n"); + } + + if (!defined($size)) { + # $output->write("$type_name: can't find type\n"); + } elsif (defined($count)) { + if ($count =~ /^\d+$/) { + $size *= int($count); + } elsif (defined($count = $defines{$count})) { + $size *= int($count); + } else { + $output->write("$type_name: can't parse type\n"); + $size = undef; + } + } elsif (defined($bits)) { + $size = -$bits; + } + + return $size; +} + foreach my $file (@files) { $progress_current++; @@ -136,13 +256,32 @@ my $found_type = sub { $type = shift; - my $pack = $packs[$#packs]; - $type->pack($pack); + &$update_output(); + + if (!defined($type->pack)) { + my $pack = $packs[$#packs]; + $type->pack($pack); + } my $name = $type->name; $file2types{$file}{$name} = $type; - &$update_output(); + my $size = $type->size(\&find_size); + if (defined($size)) { + foreach my $field ($type->fields(\&find_size)) { + my $field_type_name = $field->type_name; + my $field_name = $field->name; + my $field_size = $field->size; + my $field_offset = $field->offset; + + # $output->write("$name: $field_type_name: $field_name: $field_offset: $field_size\n"); + } + # $output->write("$name: $size\n"); + + $type_name2type{$name} = $type; + } else { + # $output->write("$name: can't find size\n"); + } return 1; }; @@ -212,67 +351,6 @@ } ######################################################################## -# output_field_size - -my %type_name2size; - -sub field_size { - my $name = shift; - my $field_type = shift; - my $field_name = shift; - - local $_ = $field_type; - - my $count; - my $bits; - if (s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) { - $count = $2; - $bits = $3; - } - - my $size; - if (defined($size = $type_name2size{$field_type})) { - # Nothing - } elsif(/^(?:(?:signed\s+|unsigned\s+)?char|CHAR|BYTE|UCHAR)$/) { - $size = 1; - } elsif (/^(?:(?:signed\s+|unsigned\s+)?short|ATOM|UWORD|WCHAR|WORD)$/) { - $size = 2; - } elsif (/^(?:FILETIME|LARGE_INTEGER|LONGLONG|ULONGLONG)$/) { - $size = 8; - } elsif (/^(?:EMR|POINTL?|SIZEL)$/) { - $size = 8; - } elsif (/^(?:RECTL?|SYSTEMTIME)$/) { - $size = 16; - } elsif (/^(?:CRITICAL_SECTION|XFORM)$/) { - $size = 24; - } elsif (/^(?:DCB)$/) { - $size = 28; - } elsif (/^(?:EXCEPTION_RECORD)$/) { - $size = 80; - } elsif (/^(?:struct|union)$/) { - $output->write("$name:$field_name: can't parse type '$field_type'\n"); - $size = 4; - } else { - $size = 4; - } - - if (defined($count)) { - if ($count =~ /^\d+$/) { - return $size * int($count); - } elsif ($count =~ /^ANYSIZE_ARRAY$/) { - return $size; - } else { - $output->write("$name:$field_name: can't parse type '$field_type'\n"); - return $size; # Not correct. - } - } elsif (defined($bits)) { - return -$bits; - } else { - return $size; - } -} - -######################################################################## # output_test_pack sub output_test_pack { @@ -290,57 +368,54 @@ $type_name_not_used{$type_name} = 1; } - # FIXME: Topological sort of @type_names - foreach my $include (@includes) { my $types = $file2types{"include/$include"}; - foreach my $type_name (@type_names) { + foreach my $type_name (@type_names) { my $type = $$types{$type_name}; if (!defined($type)) { next; } $type_name_not_used{$type_name} = 0; - + my $pack = $type->pack; - my $offset = 0; - my $offset_bits = 0; - print OUT " /* $type_name */\n"; - foreach my $field ($type->fields) { - (my $field_type, my $field_name) = @$field; - - my $field_size = field_size($type_name, $field_type, $field_name); - if ($field_size >= 0) { - if ($offset_bits) { - $offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack)); - $offset_bits = 0; - } - - my $field_offset = $offset; - if ($field_name ne "") { - print OUT " ok(FIELD_OFFSET($type_name, $field_name) == $field_offset,\n"; - print OUT " \"FIELD_OFFSET($type_name, $field_name) == %ld (expected $field_offset)\",\n"; - print OUT " FIELD_OFFSET($type_name, $field_name)); /* $field_type */\n"; + + foreach my $field ($type->fields(\&find_size)) { + my $field_type_name = $field->type_name; + my $field_name = $field->name; + my $field_size = $field->size; + my $field_offset = $field->offset; + my $field_align = $field->align; + + next if $field_name eq "" || (defined($field_size) && $field_size < 0); + + if (defined($field_size) && defined($field_offset)) { + print OUT " ok(FIELD_OFFSET($type_name, $field_name) == $field_offset,\n"; + print OUT " \"FIELD_OFFSET($type_name, $field_name) == %ld (expected $field_offset)\",\n"; + print OUT " FIELD_OFFSET($type_name, $field_name)); /* $field_type_name */\n"; + + if (0) { + print OUT " ok(TYPE_ALIGNMENT($field_type_name) == $field_align,\n"; + print OUT " \"TYPE_ALIGNMENT($field_type_name) == %d (expected $field_align)\",\n"; + print OUT " TYPE_ALIGNMENT($field_type_name)); /* $field_name */\n"; } - - $offset += $field_size; } else { - $offset_bits += -$field_size; + $output->write("$type_name: $field_type_name: $field_name: test not generated (offset not defined)\n"); } } - - my $type_size = $offset; - if ($type_size % $pack != 0) { - $type_size = (int($type_size / $pack) + 1) * $pack; - } - $type_name2size{$type_name} = $type_size; - print OUT " ok(sizeof($type_name) == $type_size, "; - print OUT "\"sizeof($type_name) == %d (expected $type_size)\", "; - print OUT "sizeof($type_name));\n"; - print OUT "\n"; + my $type_size = $type->size; + + if (defined($type_size)) { + print OUT " ok(sizeof($type_name) == $type_size, "; + print OUT "\"sizeof($type_name) == %d (expected $type_size)\", "; + print OUT "sizeof($type_name));\n"; + print OUT "\n"; + } else { + $output->write("$type_name: test not generated (size not defined)\n"); + } } }