Reorganized the code for better support of data structures parsing.
diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm
index 9e97d4c..6384a0e 100644
--- a/tools/winapi/c_parser.pm
+++ b/tools/winapi/c_parser.pm
@@ -1112,8 +1112,8 @@
my $match;
while($self->_parse_c('(?:const|inline|extern(?:\s+\"C\")?|EXTERN_C|static|volatile|' .
- '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|volatile|' .
- '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) {
diff --git a/tools/winapi/c_type.pm b/tools/winapi/c_type.pm
index 31772d8..a6afc7b 100644
--- a/tools/winapi/c_type.pm
+++ b/tools/winapi/c_type.pm
@@ -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;
- my $count = scalar(@field_types);
-
+ if (defined($find_size)) {
+ $self->_refresh($find_size);
+ }
+
+ my $count = $self->field_count;
+
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_types;
+ 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_type_names[$$number];
}
1;
diff --git a/tools/winapi/tests.dat b/tools/winapi/tests.dat
index 9db5203..25e74f3 100644
--- a/tools/winapi/tests.dat
+++ b/tools/winapi/tests.dat
@@ -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
diff --git a/tools/winapi/winapi_extract b/tools/winapi/winapi_extract
index 7216349..d89e8e7 100755
--- a/tools/winapi/winapi_extract
+++ b/tools/winapi/winapi_extract
@@ -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");
}
}
}
diff --git a/tools/winapi/winapi_test b/tools/winapi/winapi_test
index 7fc9cff..1b74ab6 100755
--- a/tools/winapi/winapi_test
+++ b/tools/winapi/winapi_test
@@ -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;
}
}
}
- @files = sort(keys(%files));
+
+ 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;
+ }
+ }
+ }
+ }
}
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|signed)$/) {
+ $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;
+
+ 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";
}
-
- 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";
- }
-
- $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");
+ }
}
}