Reorganized the code for better support of data structures parsing.

This commit is contained in:
Patrik Stridvall 2002-10-09 18:12:02 +00:00 committed by Alexandre Julliard
parent 7bdf2ff9f4
commit 91a3686853
5 changed files with 494 additions and 171 deletions

View File

@ -1112,8 +1112,8 @@ sub parse_c_function {
my $match; my $match;
while($self->_parse_c('(?:const|inline|extern(?:\s+\"C\")?|EXTERN_C|static|volatile|' . 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)|' . 'signed(?=\s+__int64\b|\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)|' . '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)', 'long(?=\s+double\b|\s+int\b|\s+long\b))(?=\b)',
\$_, \$line, \$column, \$match)) \$_, \$line, \$column, \$match))
{ {
@ -1654,22 +1654,22 @@ sub parse_c_typedef {
if ($kind =~ /^struct|union$/) { if ($kind =~ /^struct|union$/) {
my $name = ""; my $name = "";
my @field_types = (); my @field_type_names = ();
my @field_names = (); my @field_names = ();
my $match; 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_linkage;
my $field_type; my $field_type_name;
my $field_name; my $field_name;
if ($self->parse_c_variable(\$match, \$line, \$column, \$field_linkage, \$field_type, \$field_name)) { if ($self->parse_c_variable(\$match, \$line, \$column, \$field_linkage, \$field_type_name, \$field_name)) {
$field_type =~ s/\s+/ /g; $field_type_name =~ s/\s+/ /g;
push @field_types, $field_type; push @field_type_names, $field_type_name;
push @field_names, $field_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) { } elsif ($match) {
$self->_parse_c_error($_, $line, $column, "typedef $kind: '$match'"); $self->_parse_c_error($_, $line, $column, "typedef $kind: '$match'");
} }
@ -1708,7 +1708,7 @@ sub parse_c_typedef {
$type->kind($kind); $type->kind($kind);
$type->_name($_name); $type->_name($_name);
$type->name($name); $type->name($name);
$type->field_types([@field_types]); $type->field_type_names([@field_type_names]);
$type->field_names([@field_names]); $type->field_names([@field_names]);
&$$found_type($type); &$$found_type($type);
@ -1759,9 +1759,43 @@ sub parse_c_typedef {
# FIXME: Not correct # FIXME: Not correct
# $output->write("typedef:$name:$_name\n"); # $output->write("typedef:$name:$_name\n");
} }
} elsif ($self->_parse_c("typedef", \$_, \$line, \$column)) { } 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 { } else {
return 0; return 0;
} }
@ -1808,8 +1842,8 @@ sub parse_c_variable {
my $match; my $match;
while($self->_parse_c('(?:const|inline|extern(?:\s+\"C\")?|EXTERN_C|static|volatile|' . 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)|' . 'signed(?=\s+__int64\b|\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)|' . '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)', 'long(?=\s+double\b|\s+int\b|\s+long\b))(?=\b)',
\$_, \$line, \$column, \$match)) \$_, \$line, \$column, \$match))
{ {
@ -1824,6 +1858,8 @@ sub parse_c_variable {
if($finished) { if($finished) {
# Nothing # Nothing
} elsif(/^$/) {
return 0;
} elsif(s/^(enum|struct|union)(?:\s+(\w+))?\s*\{//s) { } elsif(s/^(enum|struct|union)(?:\s+(\w+))?\s*\{//s) {
my $kind = $1; my $kind = $1;
my $_name = $2; my $_name = $2;
@ -1865,6 +1901,8 @@ sub parse_c_variable {
$name = $2; $name = $2;
$finished = 1; $finished = 1;
} else {
$self->_parse_c_warning($_, $line, $column, "variable", "'$_'");
} }
if($finished) { if($finished) {

View File

@ -20,6 +20,8 @@ package c_type;
use strict; use strict;
use output qw($output);
sub new { sub new {
my $proto = shift; my $proto = shift;
my $class = ref($proto) || $proto; my $class = ref($proto) || $proto;
@ -83,18 +85,45 @@ sub pack {
sub fields { sub fields {
my $self = shift; my $self = shift;
my @field_types = @{$self->field_types}; my $find_size = shift;
my @field_names = @{$self->field_names};
my $count = scalar(@field_types); if (defined($find_size)) {
$self->_refresh($find_size);
}
my $count = $self->field_count;
my @fields = (); my @fields = ();
for (my $n = 0; $n < $count; $n++) { 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; 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 { sub field_names {
my $self = shift; my $self = shift;
my $field_names = \${$self->{FIELD_NAMES}}; my $field_names = \${$self->{FIELD_NAMES}};
@ -106,15 +135,186 @@ sub field_names {
return $$field_names; return $$field_names;
} }
sub field_types { sub field_offsets {
my $self = shift; 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; 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; 1;

View File

@ -8,6 +8,9 @@ Unit tests for data structure packing
%include %include
basetsd.h
winnt.h
windef.h
winbase.h winbase.h
%struct %struct
@ -25,11 +28,11 @@ EXCEPTION_DEBUG_INFO
EXIT_PROCESS_DEBUG_INFO EXIT_PROCESS_DEBUG_INFO
EXIT_THREAD_DEBUG_INFO EXIT_THREAD_DEBUG_INFO
# FILETIME # FILETIME
# HW_PROFILE_INFOA HW_PROFILE_INFOA
LDT_ENTRY # LDT_ENTRY
LOAD_DLL_DEBUG_INFO LOAD_DLL_DEBUG_INFO
MEMORYSTATUS MEMORYSTATUS
# OFSTRUCT OFSTRUCT
OSVERSIONINFOA OSVERSIONINFOA
OSVERSIONINFOEXA OSVERSIONINFOEXA
OSVERSIONINFOEXW OSVERSIONINFOEXW
@ -44,7 +47,7 @@ STARTUPINFOA
STARTUPINFOW STARTUPINFOW
SYSLEVEL SYSLEVEL
SYSTEMTIME SYSTEMTIME
SYSTEM_INFO # SYSTEM_INFO
SYSTEM_POWER_STATUS SYSTEM_POWER_STATUS
TIME_ZONE_INFORMATION TIME_ZONE_INFORMATION
UNLOAD_DLL_DEBUG_INFO UNLOAD_DLL_DEBUG_INFO
@ -63,6 +66,9 @@ Unit tests for data structure packing
%include %include
basetsd.h
winnt.h
windef.h
wingdi.h wingdi.h
%struct %struct
@ -71,20 +77,20 @@ ABC
ABCFLOAT ABCFLOAT
BITMAP BITMAP
BITMAPCOREHEADER BITMAPCOREHEADER
# BITMAPCOREINFO BITMAPCOREINFO
BITMAPFILEHEADER BITMAPFILEHEADER
# BITMAPINFO BITMAPINFO
BITMAPINFOHEADER BITMAPINFOHEADER
# BITMAPV4HEADER BITMAPV4HEADER
# BITMAPV5HEADER BITMAPV5HEADER
BLENDFUNCTION BLENDFUNCTION
# CHARSETINFO CHARSETINFO
CIEXYZ CIEXYZ
# CIEXYZTRIPLE CIEXYZTRIPLE
# COLORADJUSTMENT COLORADJUSTMENT
# DEVMODEA # DEVMODEA
# DEVMODEW # DEVMODEW
# DIBSECTION DIBSECTION
DISPLAY_DEVICEA DISPLAY_DEVICEA
DISPLAY_DEVICEW DISPLAY_DEVICEW
DOCINFOA DOCINFOA
@ -94,23 +100,23 @@ EMRABORTPATH
EMRANGLEARC EMRANGLEARC
EMRARC EMRARC
EMRBITBLT EMRBITBLT
# EMRCREATEBRUSHINDIRECT EMRCREATEBRUSHINDIRECT
# EMRCREATECOLORSPACE EMRCREATECOLORSPACE
# EMRCREATECOLORSPACEW # EMRCREATECOLORSPACEW
EMRCREATEDIBPATTERNBRUSHPT EMRCREATEDIBPATTERNBRUSHPT
EMRCREATEMONOBRUSH EMRCREATEMONOBRUSH
# EMRCREATEPALETTE EMRCREATEPALETTE
# EMRCREATEPEN EMRCREATEPEN
EMRDELETECOLORSPACE EMRDELETECOLORSPACE
EMRDELETEOBJECT EMRDELETEOBJECT
EMRELLIPSE EMRELLIPSE
EMREOF EMREOF
EMREXCLUDECLIPRECT EMREXCLUDECLIPRECT
# EMREXTCREATEFONTINDIRECTW EMREXTCREATEFONTINDIRECTW
# EMREXTCREATEPEN EMREXTCREATEPEN
EMREXTFLOODFILL EMREXTFLOODFILL
# EMREXTSELECTCLIPRGN # EMREXTSELECTCLIPRGN
# EMREXTTEXTOUTA EMREXTTEXTOUTA
EMRFILLPATH EMRFILLPATH
# EMRFILLRGN # EMRFILLRGN
EMRFORMAT EMRFORMAT
@ -123,12 +129,12 @@ EMRLINETO
EMRMASKBLT EMRMASKBLT
EMRMODIFYWORLDTRANSFORM EMRMODIFYWORLDTRANSFORM
EMROFFSETCLIPRGN EMROFFSETCLIPRGN
# EMRPIXELFORMAT EMRPIXELFORMAT
EMRPLGBLT EMRPLGBLT
# EMRPOLYDRAW # EMRPOLYDRAW
EMRPOLYLINE EMRPOLYLINE
EMRPOLYPOLYLINE EMRPOLYPOLYLINE
# EMRPOLYTEXTOUTA EMRPOLYTEXTOUTA
EMRRESIZEPALETTE EMRRESIZEPALETTE
EMRRESTOREDC EMRRESTOREDC
EMRROUNDRECT EMRROUNDRECT
@ -138,7 +144,7 @@ EMRSELECTPALETTE
EMRSETARCDIRECTION EMRSETARCDIRECTION
EMRSETBKCOLOR EMRSETBKCOLOR
EMRSETBRUSHORGEX EMRSETBRUSHORGEX
# EMRSETCOLORADJUSTMENT EMRSETCOLORADJUSTMENT
EMRSETDIBITSTODEIVCE EMRSETDIBITSTODEIVCE
EMRSETMAPPERFLAGS EMRSETMAPPERFLAGS
EMRSETMITERLIMIT EMRSETMITERLIMIT
@ -150,30 +156,30 @@ EMRSETWORLDTRANSFORM
EMRSTRETCHBLT EMRSTRETCHBLT
EMRSTRETCHDIBITS EMRSTRETCHDIBITS
EMRTEXT EMRTEXT
# ENHMETAHEADER ENHMETAHEADER
ENHMETARECORD ENHMETARECORD
# ENUMLOGFONTA ENUMLOGFONTA
# ENUMLOGFONTEXA ENUMLOGFONTEXA
# ENUMLOGFONTEXW ENUMLOGFONTEXW
# ENUMLOGFONTW ENUMLOGFONTW
# EXTLOGFONTA EXTLOGFONTA
# EXTLOGFONTW EXTLOGFONTW
EXTLOGPEN EXTLOGPEN
# FIXED FIXED
FONTSIGNATURE FONTSIGNATURE
GCP_RESULTSA GCP_RESULTSA
GCP_RESULTSW GCP_RESULTSW
# GLYPHMETRICS GLYPHMETRICS
GRADIENT_RECT GRADIENT_RECT
GRADIENT_TRIANGLE GRADIENT_TRIANGLE
HANDLETABLE HANDLETABLE
KERNINGPAIR KERNINGPAIR
LOCALESIGNATURE LOCALESIGNATURE
LOGBRUSH LOGBRUSH
# LOGCOLORSPACEA LOGCOLORSPACEA
# LOGCOLORSPACEW LOGCOLORSPACEW
# LOGFONTA LOGFONTA
# LOGFONTW LOGFONTW
LOGPALETTE LOGPALETTE
LOGPEN LOGPEN
MAT2 MAT2
@ -181,8 +187,8 @@ METAFILEPICT
METAHEADER METAHEADER
METARECORD METARECORD
# NEWTEXTMETRICA # NEWTEXTMETRICA
# NEWTEXTMETRICEXA NEWTEXTMETRICEXA
# NEWTEXTMETRICEXW NEWTEXTMETRICEXW
# NEWTEXTMETRICW # NEWTEXTMETRICW
# OUTLINETEXTMETRICA # OUTLINETEXTMETRICA
# OUTLINETEXTMETRICW # OUTLINETEXTMETRICW
@ -191,18 +197,18 @@ PALETTEENTRY
PELARRAY PELARRAY
PIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR
POINTFX POINTFX
# POLYTEXTA POLYTEXTA
# POLYTEXTW POLYTEXTW
# RASTERIZER_STATUS # RASTERIZER_STATUS
RGBQUAD RGBQUAD
# RGBTRIPLE # RGBTRIPLE
# RGNDATA # RGNDATA
# RGNDATAHEADER RGNDATAHEADER
TEXTMETRICA TEXTMETRICA
TEXTMETRICW TEXTMETRICW
# TRIVERTEX TRIVERTEX
# TTPOLYCURVE TTPOLYCURVE
# TTPOLYGONHEADER TTPOLYGONHEADER
XFORM XFORM
%%%dlls/user/tests %%%dlls/user/tests
@ -215,6 +221,9 @@ Unit tests for data structure packing
%include %include
basetsd.h
winnt.h
windef.h
winbase.h winbase.h
winuser.h winuser.h

View File

@ -328,13 +328,14 @@ foreach my $file (@h_files, @c_files) {
my $name = $type->name; my $name = $type->name;
foreach my $field ($type->fields) { 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 ($options->struct) {
if ($name) { if ($name) {
$output->write("$name:$field_type:$field_name\n"); $output->write("$name:$field_type_name:$field_name\n");
} else { } else {
$output->write("$kind $_name:$field_type:$field_name\n"); $output->write("$kind $_name:$field_type_name:$field_name\n");
} }
} }
} }

View File

@ -57,11 +57,23 @@ my @files = ();
foreach my $test_dir (@test_dirs) { foreach my $test_dir (@test_dirs) {
my @includes = $tests->get_section($test_dir, $test, "include"); my @includes = $tests->get_section($test_dir, $test, "include");
foreach my $include (@includes) { 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; my %file2types;
@ -70,6 +82,114 @@ my $progress_output;
my $progress_current = 0; my $progress_current = 0;
my $progress_max = scalar(@files); 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) { foreach my $file (@files) {
$progress_current++; $progress_current++;
@ -136,13 +256,32 @@ foreach my $file (@files) {
my $found_type = sub { my $found_type = sub {
$type = shift; $type = shift;
&$update_output();
if (!defined($type->pack)) {
my $pack = $packs[$#packs]; my $pack = $packs[$#packs];
$type->pack($pack); $type->pack($pack);
}
my $name = $type->name; my $name = $type->name;
$file2types{$file}{$name} = $type; $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; return 1;
}; };
@ -211,67 +350,6 @@ sub output_footer {
print OUT "}\n"; print OUT "}\n";
} }
########################################################################
# 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 # output_test_pack
@ -290,8 +368,6 @@ sub output_test_pack {
$type_name_not_used{$type_name} = 1; $type_name_not_used{$type_name} = 1;
} }
# FIXME: Topological sort of @type_names
foreach my $include (@includes) { foreach my $include (@includes) {
my $types = $file2types{"include/$include"}; my $types = $file2types{"include/$include"};
@ -304,43 +380,42 @@ sub output_test_pack {
my $pack = $type->pack; my $pack = $type->pack;
my $offset = 0;
my $offset_bits = 0;
print OUT " /* $type_name */\n"; 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); foreach my $field ($type->fields(\&find_size)) {
if ($field_size >= 0) { my $field_type_name = $field->type_name;
if ($offset_bits) { my $field_name = $field->name;
$offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack)); my $field_size = $field->size;
$offset_bits = 0; my $field_offset = $field->offset;
} my $field_align = $field->align;
my $field_offset = $offset; next if $field_name eq "" || (defined($field_size) && $field_size < 0);
if ($field_name ne "") {
if (defined($field_size) && defined($field_offset)) {
print OUT " ok(FIELD_OFFSET($type_name, $field_name) == $field_offset,\n"; 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) == %ld (expected $field_offset)\",\n";
print OUT " FIELD_OFFSET($type_name, $field_name)); /* $field_type */\n"; print OUT " FIELD_OFFSET($type_name, $field_name)); /* $field_type_name */\n";
}
$offset += $field_size; 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";
}
} else { } 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; my $type_size = $type->size;
if ($type_size % $pack != 0) {
$type_size = (int($type_size / $pack) + 1) * $pack;
}
$type_name2size{$type_name} = $type_size;
if (defined($type_size)) {
print OUT " ok(sizeof($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) == %d (expected $type_size)\", ";
print OUT "sizeof($type_name));\n"; print OUT "sizeof($type_name));\n";
print OUT "\n"; print OUT "\n";
} else {
$output->write("$type_name: test not generated (size not defined)\n");
}
} }
} }