From 65442cd763c35e1e486dad3585f27780a529f82e Mon Sep 17 00:00:00 2001 From: Patrik Stridvall Date: Fri, 11 Oct 2002 17:53:13 +0000 Subject: [PATCH] - Improved alignment and offset calculations. - Reorganized and improved enum/union/struct parsing. --- tools/winapi/c_parser.pm | 390 ++++++++++++++++++++++-------------- tools/winapi/c_type.pm | 143 +++++++++---- tools/winapi/tests.dat | 271 ++++++++++++++++--------- tools/winapi/winapi_extract | 2 +- tools/winapi/winapi_test | 136 +++++++++---- 5 files changed, 622 insertions(+), 320 deletions(-) diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm index 6384a0e4983..1e736ab0f09 100644 --- a/tools/winapi/c_parser.pm +++ b/tools/winapi/c_parser.pm @@ -696,6 +696,80 @@ sub parse_c_declarations { return 1; } +######################################################################## +# parse_c_enum + +sub parse_c_enum { + my $self = shift; + + my $refcurrent = shift; + my $refline = shift; + my $refcolumn = shift; + + local $_ = $$refcurrent; + my $line = $$refline; + my $column = $$refcolumn; + + $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column); + + if (!s/^enum\s+((?:MSVCRT|WS)\(\s*\w+\s*\)|\w+)?\s*\{\s*//s) { + return 0; + } + my $_name = $1 || ""; + + $self->_update_c_position($&, \$line, \$column); + + my $name = ""; + + my $match; + while ($self->_parse_c_on_same_level_until_one_of(',', \$_, \$line, \$column, \$match)) { + if ($match) { + if ($match !~ /^(\w+)\s*(?:=\s*(.*?)\s*)?$/) { + $self->_parse_c_error($_, $line, $column, "enum"); + } + my $enum_name = $1; + my $enum_value = $2 || ""; + + # $output->write("enum:$_name:$enum_name:$enum_value\n"); + } + + if ($self->_parse_c(',', \$_, \$line, \$column)) { + next; + } elsif ($self->_parse_c('}', \$_, \$line, \$column)) { + # FIXME: Kludge + my $tuple = "($_)"; + my $tuple_line = $line; + my $tuple_column = $column - 1; + + my @arguments; + my @argument_lines; + my @argument_columns; + + if(!$self->parse_c_tuple(\$tuple, \$tuple_line, \$tuple_column, + \@arguments, \@argument_lines, \@argument_columns)) + { + $self->_parse_c_error($_, $line, $column, "enum"); + } + + # FIXME: Kludge + if ($#arguments >= 0) { + $name = $arguments[0]; + } + + last; + } else { + $self->_parse_c_error($_, $line, $column, "enum"); + } + } + + $self->_update_c_position($_, \$line, \$column); + + $$refcurrent = $_; + $$refline = $line; + $$refcolumn = $column; +} + + ######################################################################## # parse_c_expression @@ -1502,6 +1576,104 @@ sub parse_c_statements { return 1; } +######################################################################## +# parse_c_struct_union + +sub parse_c_struct_union { + my $self = shift; + + my $refcurrent = shift; + my $refline = shift; + my $refcolumn = shift; + + my $refkind = shift; + my $ref_name = shift; + my $reffield_type_names = shift; + my $reffield_names = shift; + my $refnames = shift; + + local $_ = $$refcurrent; + my $line = $$refline; + my $column = $$refcolumn; + + my $kind; + my $_name; + my @field_type_names = (); + my @field_names = (); + my @names = (); + + $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column); + + if (!s/^(struct\s+|union\s+)((?:MSVCRT|WS)\(\s*\w+\s*\)|\w+)?\s*\{\s*//s) { + return 0; + } + $kind = $1; + $_name = $2 || ""; + + $self->_update_c_position($&, \$line, \$column); + + $kind =~ s/\s+//g; + + my $match; + while ($_ && $self->_parse_c_on_same_level_until_one_of(';', \$_, \$line, \$column, \$match)) + { + my $field_linkage; + my $field_type_name; + my $field_name; + + if ($self->parse_c_variable(\$match, \$line, \$column, \$field_linkage, \$field_type_name, \$field_name)) { + $field_type_name =~ s/\s+/ /g; + + push @field_type_names, $field_type_name; + push @field_names, $field_name; + # $output->write("$kind:$_name:$field_type_name:$field_name\n"); + } elsif ($match) { + $self->_parse_c_error($_, $line, $column, "typedef $kind: '$match'"); + } + + if ($self->_parse_c(';', \$_, \$line, \$column)) { + next; + } elsif ($self->_parse_c('}', \$_, \$line, \$column)) { + # FIXME: Kludge + my $tuple = "($_)"; + my $tuple_line = $line; + my $tuple_column = $column - 1; + + my @arguments; + my @argument_lines; + my @argument_columns; + + if(!$self->parse_c_tuple(\$tuple, \$tuple_line, \$tuple_column, + \@arguments, \@argument_lines, \@argument_columns)) + { + $self->_parse_c_error($_, $line, $column, "$kind"); + } + + foreach my $argument (@arguments) { + my $name = $argument; + + push @names, $name; + } + + last; + } else { + $self->_parse_c_error($_, $line, $column, "$kind"); + } + } + + $$refcurrent = $_; + $$refline = $line; + $$refcolumn = $column; + + $$refkind = $kind; + $$ref_name = $_name; + @$reffield_type_names = @field_type_names; + @$reffield_names = @field_names; + @$refnames = @names; + + return 1; +} + ######################################################################## # parse_c_tuple @@ -1634,178 +1806,104 @@ sub parse_c_typedef { my $refline = shift; my $refcolumn = shift; - my $reftype = shift; - local $_ = $$refcurrent; my $line = $$refline; my $column = $$refcolumn; my $type; - if (0) { + if (!$self->_parse_c("typedef", \$_, \$line, \$column)) { + return 0; + } + + my $finished = 0; + + if ($finished) { # Nothing - } elsif (s/^(?:typedef\s+)?(enum\s+|struct\s+|union\s+)((?:MSVCRT|WS)\(\s*\w+\s*\)|\w+)?\s*\{\s*//s) { - $self->_update_c_position($&, \$line, \$column); + } elsif ($self->parse_c_enum(\$_, \$line, \$column)) { + $finished = 1; + } - my $kind = $1; - my $_name = $2 || ""; - - $kind =~ s/\s+//g; - - if ($kind =~ /^struct|union$/) { - my $name = ""; - my @field_type_names = (); - my @field_names = (); - - my $match; - while ($_ && $self->_parse_c_on_same_level_until_one_of(';', \$_, \$line, \$column, \$match)) - { - my $field_linkage; - my $field_type_name; - my $field_name; - - if ($self->parse_c_variable(\$match, \$line, \$column, \$field_linkage, \$field_type_name, \$field_name)) { - $field_type_name =~ s/\s+/ /g; - - push @field_type_names, $field_type_name; - push @field_names, $field_name; - # $output->write("$kind:$_name:$field_type_name:$field_name\n"); - } elsif ($match) { - $self->_parse_c_error($_, $line, $column, "typedef $kind: '$match'"); - } - - if ($self->_parse_c(';', \$_, \$line, \$column)) { - next; - } elsif ($self->_parse_c('}', \$_, \$line, \$column)) { - # FIXME: Kludge - my $tuple = "($_)"; - my $tuple_line = $line; - my $tuple_column = $column - 1; - - my @arguments; - my @argument_lines; - my @argument_columns; - - if(!$self->parse_c_tuple(\$tuple, \$tuple_line, \$tuple_column, - \@arguments, \@argument_lines, \@argument_columns)) - { - $self->_parse_c_error($_, $line, $column, "typedef $kind"); - } - - # FIXME: Kludge - if ($#arguments >= 0) { - $name = $arguments[0]; - } - - last; - } else { - $self->_parse_c_error($_, $line, $column, "typedef $kind"); - } - } - - my $type = &$$create_type(); - - $type->kind($kind); - $type->_name($_name); - $type->name($name); - $type->field_type_names([@field_type_names]); - $type->field_names([@field_names]); - - &$$found_type($type); - } else { - my $name = ""; - - my $match; - while ($self->_parse_c_on_same_level_until_one_of(',', \$_, \$line, \$column, \$match)) { - if ($match) { - if ($match !~ /^(\w+)\s*(?:=\s*(.*?)\s*)?$/) { - $self->_parse_c_error($_, $line, $column, "typedef $kind"); - } - my $enum_name = $1; - my $enum_value = $2 || ""; - - # $output->write("$kind:$_name:$enum_name:$enum_value\n"); - } - - if ($self->_parse_c(',', \$_, \$line, \$column)) { - next; - } elsif ($self->_parse_c('}', \$_, \$line, \$column)) { - # FIXME: Kludge - my $tuple = "($_)"; - my $tuple_line = $line; - my $tuple_column = $column - 1; - - my @arguments; - my @argument_lines; - my @argument_columns; - - if(!$self->parse_c_tuple(\$tuple, \$tuple_line, \$tuple_column, - \@arguments, \@argument_lines, \@argument_columns)) - { - $self->_parse_c_error($_, $line, $column, "typedef $kind"); - } - - # FIXME: Kludge - if ($#arguments >= 0) { - $name = $arguments[0]; - } - - last; - } else { - $self->_parse_c_error($_, $line, $column, "typedef $kind"); - } - } - - # FIXME: Not correct - # $output->write("typedef:$name:$_name\n"); - } - } elsif ($self->_parse_c("typedef", \$_, \$line, \$column)) { - 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 $kind; + my $_name; + my @field_type_names; + my @field_names; + my @names; + if ($finished) { + # Nothing + } elsif ($self->parse_c_struct_union(\$_, \$line, \$column, + \$kind, \$_name, \@field_type_names, \@field_names, \@names)) + { + my $base_name; + foreach my $name (@names) { + if ($name =~ /^\w+$/) { my $type = &$$create_type(); - if (length($name) == 0) { - $self->_parse_c_error($_, $line, $column, "typedef"); - } + $type->kind($kind); + $type->_name($_name); + $type->name($name); + $type->field_type_names([@field_type_names]); + $type->field_names([@field_names]); + + &$$found_type($type); + + $base_name = $name; + } elsif (!defined($base_name)) { + $self->_parse_c_error($_, $line, $column, "typedef 1"); + } elsif ($name =~ /^(\*+)\s*(?:RESTRICTED_POINTER\s+)?(\w+)$/) { + my $type_name = "$base_name $1"; + $name = $2; + + my $type = &$$create_type(); $type->kind(""); $type->name($name); - $type->pack(1); $type->field_type_names([$type_name]); $type->field_names([""]); - &$$found_type($type); + &$$found_type($type); + } else { + $self->_parse_c_error($_, $line, $column, "typedef 2"); + } + } + + $finished = 1; + } + + my $linkage; + my $type_name; + my $name; + if ($finished) { + # Nothing + } elsif ($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"); } - if (0 && $_ && !/^,/) { - $self->_parse_c_error($_, $line, $column, "typedef"); - } - } else { - $self->_parse_c_error($_, $line, $column, "typedef"); + $type->kind(""); + $type->name($name); + $type->field_type_names([$type_name]); + $type->field_names([""]); + + &$$found_type($type); } - } 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); + if (0 && $_ && !/^,/) { + $self->_parse_c_error($_, $line, $column, "typedef"); + } } else { - return 0; + $self->_parse_c_error($_, $line, $column, "typedef"); } $$refcurrent = $_; $$refline = $line; $$refcolumn = $column; - $$reftype = $type; - return 1; } @@ -1860,7 +1958,7 @@ sub parse_c_variable { # Nothing } elsif(/^$/) { return 0; - } elsif(s/^(enum|struct|union)(?:\s+(\w+))?\s*\{//s) { + } elsif (s/^(enum\s+|struct\s+|union\s+)((?:MSVCRT|WS)\(\s*\w+\s*\)|\w+)?\s*\{\s*//s) { my $kind = $1; my $_name = $2; $self->_update_c_position($&, \$line, \$column); diff --git a/tools/winapi/c_type.pm b/tools/winapi/c_type.pm index a6afc7bac80..ec49819e0de 100644 --- a/tools/winapi/c_type.pm +++ b/tools/winapi/c_type.pm @@ -31,13 +31,36 @@ sub new { return $self; } +######################################################################## +# set_find_align_callback +# +sub set_find_align_callback { + my $self = shift; + + my $find_align = \${$self->{FIND_ALIGN}}; + + $$find_align = shift; +} + +######################################################################## +# set_find_size_callback +# +sub set_find_size_callback { + my $self = shift; + + my $find_size = \${$self->{FIND_SIZE}}; + + $$find_size = shift; +} + sub kind { my $self = shift; my $kind = \${$self->{KIND}}; + my $dirty = \${$self->{DIRTY}}; local $_ = shift; - if(defined($_)) { $$kind = $_; } + if(defined($_)) { $$kind = $_; $$dirty = 1; } return $$kind; } @@ -45,10 +68,11 @@ sub kind { sub _name { my $self = shift; my $_name = \${$self->{_NAME}}; + my $dirty = \${$self->{DIRTY}}; local $_ = shift; - if(defined($_)) { $$_name = $_; } + if(defined($_)) { $$_name = $_; $$dirty = 1; } return $$_name; } @@ -56,10 +80,11 @@ sub _name { sub name { my $self = shift; my $name = \${$self->{NAME}}; + my $dirty = \${$self->{DIRTY}}; local $_ = shift; - if(defined($_)) { $$name = $_; } + if(defined($_)) { $$name = $_; $$dirty = 1; } if($$name) { return $$name; @@ -74,22 +99,27 @@ sub name { sub pack { my $self = shift; my $pack = \${$self->{PACK}}; + my $dirty = \${$self->{DIRTY}}; local $_ = shift; - if(defined($_)) { $$pack = $_; } + if(defined($_)) { $$pack = $_; $$dirty = 1; } return $$pack; } -sub fields { +sub align { my $self = shift; - my $find_size = shift; + my $align = \${$self->{ALIGN}}; - if (defined($find_size)) { - $self->_refresh($find_size); - } + $self->_refresh(); + + return $$align; +} + +sub fields { + my $self = shift; my $count = $self->field_count; @@ -101,15 +131,20 @@ sub fields { return @fields; } +sub field_base_sizes { + my $self = shift; + my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}}; + + $self->_refresh(); + + return $$field_base_sizes; +} + sub field_aligns { my $self = shift; my $field_aligns = \${$self->{FIELD_ALIGNS}}; - my $find_size = shift; - - if (defined($find_size)) { - $self->_refresh($find_size); - } + $self->_refresh(); return $$field_aligns; } @@ -127,10 +162,11 @@ sub field_count { sub field_names { my $self = shift; my $field_names = \${$self->{FIELD_NAMES}}; + my $dirty = \${$self->{DIRTY}}; local $_ = shift; - if(defined($_)) { $$field_names = $_; } + if(defined($_)) { $$field_names = $_; $$dirty = 1; } return $$field_names; } @@ -139,11 +175,7 @@ sub field_offsets { my $self = shift; my $field_offsets = \${$self->{FIELD_OFFSETS}}; - my $find_size = shift; - - if (defined($find_size)) { - $self->_refresh($find_size); - } + $self->_refresh(); return $$field_offsets; } @@ -152,11 +184,7 @@ sub field_sizes { my $self = shift; my $field_sizes = \${$self->{FIELD_SIZES}}; - my $find_size = shift; - - if (defined($find_size)) { - $self->_refresh($find_size); - } + $self->_refresh(); return $$field_sizes; } @@ -164,10 +192,11 @@ sub field_sizes { sub field_type_names { my $self = shift; my $field_type_names = \${$self->{FIELD_TYPE_NAMES}}; + my $dirty = \${$self->{DIRTY}}; local $_ = shift; - if(defined($_)) { $$field_type_names = $_; } + if(defined($_)) { $$field_type_names = $_; $$dirty = 1; } return $$field_type_names; } @@ -177,10 +206,7 @@ sub size { my $size = \${$self->{SIZE}}; - my $find_size = shift; - if (defined($find_size)) { - $self->_refresh($find_size); - } + $self->_refresh(); return $$size; } @@ -188,36 +214,52 @@ sub size { sub _refresh { my $self = shift; + my $dirty = \${$self->{DIRTY}}; + + return if !$$dirty; + + my $find_align = \${$self->{FIND_ALIGN}}; + my $find_size = \${$self->{FIND_SIZE}}; + + my $align = \${$self->{ALIGN}}; + my $kind = \${$self->{KIND}}; + my $size = \${$self->{SIZE}}; my $field_aligns = \${$self->{FIELD_ALIGNS}}; + my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}}; 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 $max_field_align = 0; + 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 $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 $base_size = &$$find_size($base_type_name); + my $align = &$$find_align($base_type_name); - my $align = 0; - $align = $base_size % 4 if defined($base_size); - $align = 4 if !$align; + if (defined($align)) { + $align = $pack if $align > $pack; + $max_field_align = $align if $align > $max_field_align; + + if ($offset % $align != 0) { + $offset = (int($offset / $align) + 1) * $align; + } + } if (!defined($size)) { + $$align = undef; $$size = undef; return; } elsif ($size >= 0) { @@ -227,12 +269,14 @@ sub _refresh { } $$$field_aligns[$n] = $align; + $$$field_base_sizes[$n] = $base_size; $$$field_offsets[$n] = $offset; $$$field_sizes[$n] = $size; $offset += $size; } else { $$$field_aligns[$n] = $align; + $$$field_base_sizes[$n] = $base_size; $$$field_offsets[$n] = $offset; $$$field_sizes[$n] = $size; @@ -242,12 +286,17 @@ sub _refresh { $n++; } + $$align = $pack; + $$align = $max_field_align if $max_field_align < $pack; + $$size = $offset; - if (1) { - if ($$size % $pack != 0) { - $$size = (int($$size / $pack) + 1) * $pack; + if ($$kind =~ /^(?:struct|union)$/) { + if ($$size % $$align != 0) { + $$size = (int($$size / $$align) + 1) * $$align; } } + + $$dirty = 0; } package c_type_field; @@ -277,6 +326,16 @@ sub align { return $$field_aligns[$$number]; } +sub base_size { + my $self = shift; + my $type = \${$self->{TYPE}}; + my $number = \${$self->{NUMBER}}; + + my $field_base_sizes = $$type->field_base_sizes; + + return $$field_base_sizes[$$number]; +} + sub name { my $self = shift; my $type = \${$self->{TYPE}}; diff --git a/tools/winapi/tests.dat b/tools/winapi/tests.dat index 25e74f3f2d1..1c49f473d58 100644 --- a/tools/winapi/tests.dat +++ b/tools/winapi/tests.dat @@ -1,61 +1,3 @@ -%%%dlls/kernel/tests - -%%pack - -%description - -Unit tests for data structure packing - -%include - -basetsd.h -winnt.h -windef.h -winbase.h - -%struct - -BY_HANDLE_FILE_INFORMATION -COMMCONFIG -COMMPROP -COMMTIMEOUTS -COMSTAT -CREATE_PROCESS_DEBUG_INFO -CREATE_THREAD_DEBUG_INFO -DCB -# DEBUG_EVENT -EXCEPTION_DEBUG_INFO -EXIT_PROCESS_DEBUG_INFO -EXIT_THREAD_DEBUG_INFO -# FILETIME -HW_PROFILE_INFOA -# LDT_ENTRY -LOAD_DLL_DEBUG_INFO -MEMORYSTATUS -OFSTRUCT -OSVERSIONINFOA -OSVERSIONINFOEXA -OSVERSIONINFOEXW -OSVERSIONINFOW -OUTPUT_DEBUG_STRING_INFO -OVERLAPPED -# PROCESS_HEAP_ENTRY -PROCESS_INFORMATION -RIP_INFO -SECURITY_ATTRIBUTES -STARTUPINFOA -STARTUPINFOW -SYSLEVEL -SYSTEMTIME -# SYSTEM_INFO -SYSTEM_POWER_STATUS -TIME_ZONE_INFORMATION -UNLOAD_DLL_DEBUG_INFO -WIN32_FILE_ATTRIBUTE_DATA -WIN32_FIND_DATAA -WIN32_FIND_DATAW -WIN32_STREAM_ID - %%%dlls/gdi/tests %%pack @@ -102,10 +44,10 @@ EMRARC EMRBITBLT EMRCREATEBRUSHINDIRECT EMRCREATECOLORSPACE -# EMRCREATECOLORSPACEW +EMRCREATECOLORSPACEW EMRCREATEDIBPATTERNBRUSHPT EMRCREATEMONOBRUSH -EMRCREATEPALETTE +# EMRCREATEPALETTE EMRCREATEPEN EMRDELETECOLORSPACE EMRDELETEOBJECT @@ -115,23 +57,23 @@ EMREXCLUDECLIPRECT EMREXTCREATEFONTINDIRECTW EMREXTCREATEPEN EMREXTFLOODFILL -# EMREXTSELECTCLIPRGN +EMREXTSELECTCLIPRGN EMREXTTEXTOUTA EMRFILLPATH -# EMRFILLRGN +EMRFILLRGN EMRFORMAT -# EMRFRAMERGN -# EMRGDICOMMENT -# EMRGLSBOUNDEDRECORD -# EMRGLSRECORD -# EMRINVERTRGN +EMRFRAMERGN +EMRGDICOMMENT +EMRGLSBOUNDEDRECORD +EMRGLSRECORD +EMRINVERTRGN EMRLINETO EMRMASKBLT EMRMODIFYWORLDTRANSFORM EMROFFSETCLIPRGN EMRPIXELFORMAT EMRPLGBLT -# EMRPOLYDRAW +EMRPOLYDRAW EMRPOLYLINE EMRPOLYPOLYLINE EMRPOLYTEXTOUTA @@ -148,7 +90,7 @@ EMRSETCOLORADJUSTMENT EMRSETDIBITSTODEIVCE EMRSETMAPPERFLAGS EMRSETMITERLIMIT -EMRSETPALETTEENTRIES +# EMRSETPALETTEENTRIES EMRSETPIXELV EMRSETTEXTJUSTIFICATION EMRSETVIEWPORTEXTEX @@ -180,29 +122,29 @@ LOGCOLORSPACEA LOGCOLORSPACEW LOGFONTA LOGFONTW -LOGPALETTE +# LOGPALETTE LOGPEN MAT2 METAFILEPICT METAHEADER METARECORD -# NEWTEXTMETRICA +NEWTEXTMETRICA NEWTEXTMETRICEXA NEWTEXTMETRICEXW -# NEWTEXTMETRICW -# OUTLINETEXTMETRICA -# OUTLINETEXTMETRICW -PALETTEENTRY -# PANOSE +NEWTEXTMETRICW +OUTLINETEXTMETRICA +OUTLINETEXTMETRICW +# PALETTEENTRY +PANOSE PELARRAY PIXELFORMATDESCRIPTOR POINTFX POLYTEXTA POLYTEXTW -# RASTERIZER_STATUS +RASTERIZER_STATUS RGBQUAD -# RGBTRIPLE -# RGNDATA +RGBTRIPLE +RGNDATA RGNDATAHEADER TEXTMETRICA TEXTMETRICW @@ -211,6 +153,154 @@ TTPOLYCURVE TTPOLYGONHEADER XFORM +%%%dlls/kernel/tests + +%%pack + +%description + +Unit tests for data structure packing + +%include + +basetsd.h +winnt.h +windef.h +winbase.h + +%struct + +BY_HANDLE_FILE_INFORMATION +COMMCONFIG +COMMPROP +COMMTIMEOUTS +COMSTAT +CREATE_PROCESS_DEBUG_INFO +CREATE_THREAD_DEBUG_INFO +DCB +DEBUG_EVENT +EXCEPTION_DEBUG_INFO +EXIT_PROCESS_DEBUG_INFO +EXIT_THREAD_DEBUG_INFO +# FILETIME +HW_PROFILE_INFOA +LDT_ENTRY +LOAD_DLL_DEBUG_INFO +MEMORYSTATUS +OFSTRUCT +OSVERSIONINFOA +OSVERSIONINFOEXA +OSVERSIONINFOEXW +OSVERSIONINFOW +OUTPUT_DEBUG_STRING_INFO +OVERLAPPED +PROCESS_HEAP_ENTRY +PROCESS_INFORMATION +RIP_INFO +SECURITY_ATTRIBUTES +STARTUPINFOA +STARTUPINFOW +SYSLEVEL +SYSTEMTIME +# SYSTEM_INFO +SYSTEM_POWER_STATUS +TIME_ZONE_INFORMATION +UNLOAD_DLL_DEBUG_INFO +WIN32_FILE_ATTRIBUTE_DATA +WIN32_FIND_DATAA +WIN32_FIND_DATAW +WIN32_STREAM_ID + +%%%dlls/ntdll/tests + +%%pack + +%description + +Unit tests for data structure packing + +%include + +basetsd.h +winnt.h +windef.h + +%struct + +ACCESS_ALLOWED_ACE +ACCESS_DENIED_ACE +ACE_HEADER +ACL +CONTEXT86 +# EXCEPTION_FRAME +EXCEPTION_POINTERS +EXCEPTION_RECORD +FLOATING_SAVE_AREA +FPO_DATA +GENERIC_MAPPING +IMAGE_ARCHIVE_MEMBER_HEADER +IMAGE_AUX_SYMBOL +IMAGE_BASE_RELOCATION +IMAGE_BOUND_FORWARDER_REF +IMAGE_BOUND_IMPORT_DESCRIPTOR +IMAGE_COFF_SYMBOLS_HEADER +IMAGE_DATA_DIRECTORY +IMAGE_DEBUG_DIRECTORY +IMAGE_DEBUG_MISC +IMAGE_DOS_HEADER +IMAGE_EXPORT_DIRECTORY +IMAGE_FILE_HEADER +IMAGE_FUNCTION_ENTRY +IMAGE_IMPORT_BY_NAME +# IMAGE_IMPORT_DESCRIPTOR +# IMAGE_LINENUMBER +IMAGE_LOAD_CONFIG_DIRECTORY +IMAGE_NT_HEADERS +IMAGE_OPTIONAL_HEADER +IMAGE_OS2_HEADER +# IMAGE_RELOCATION +IMAGE_RESOURCE_DATA_ENTRY +IMAGE_RESOURCE_DIRECTORY +IMAGE_RESOURCE_DIRECTORY_ENTRY +IMAGE_RESOURCE_DIRECTORY_STRING +IMAGE_RESOURCE_DIR_STRING_U +# IMAGE_SECTION_HEADER +IMAGE_SEPARATE_DEBUG_HEADER +# IMAGE_SYMBOL +IMAGE_THUNK_DATA +IMAGE_TLS_DIRECTORY +IMAGE_VXD_HEADER +# LARGE_INTEGER +LIST_ENTRY +LUID +LUID_AND_ATTRIBUTES +MEMORY_BASIC_INFORMATION +MESSAGE_RESOURCE_BLOCK +MESSAGE_RESOURCE_DATA +MESSAGE_RESOURCE_ENTRY +# NT_TIB +PRIVILEGE_SET +RTL_CRITICAL_SECTION +RTL_CRITICAL_SECTION_DEBUG +SECURITY_DESCRIPTOR +SECURITY_DESCRIPTOR_RELATIVE +# SECURITY_QUALITY_OF_SERVICE +SID +SID_AND_ATTRIBUTES +SID_IDENTIFIER_AUTHORITY +SINGLE_LIST_ENTRY +SYSTEM_ALARM_ACE +SYSTEM_AUDIT_ACE +TOKEN_DEFAULT_DACL +TOKEN_GROUPS +TOKEN_OWNER +TOKEN_PRIMARY_GROUP +TOKEN_PRIVILEGES +TOKEN_SOURCE +# TOKEN_STATISTICS +TOKEN_USER +# ULARGE_INTEGER + %%%dlls/user/tests %%pack @@ -225,11 +315,12 @@ basetsd.h winnt.h windef.h winbase.h +wingdi.h winuser.h %struct -# ACCEL +ACCEL ACCESSTIMEOUT ANIMATIONINFO CBTACTIVATESTRUCT @@ -247,7 +338,7 @@ DEBUGHOOKINFO DELETEITEMSTRUCT DLGITEMTEMPLATE DLGTEMPLATE -DRAWITEMSTRUCT +# DRAWITEMSTRUCT DRAWTEXTPARAMS EVENTMSG FILTERKEYS @@ -259,9 +350,9 @@ HELPWININFOW HIGHCONTRASTA HIGHCONTRASTW ICONINFO -# ICONMETRICSA -# ICONMETRICSW -# INPUT +ICONMETRICSA +ICONMETRICSW +INPUT KBDLLHOOKSTRUCT KEYBDINPUT MDICREATESTRUCTA @@ -271,13 +362,13 @@ MEASUREITEMSTRUCT MENUINFO MENUITEMINFOA MENUITEMINFOW -# MENUITEMTEMPLATE +MENUITEMTEMPLATE MENUITEMTEMPLATEHEADER MINIMIZEDMETRICS MINMAXINFO MONITORINFO -# MONITORINFOEXA -# MONITORINFOEXW +MONITORINFOEXA +MONITORINFOEXW MOUSEHOOKSTRUCT MOUSEINPUT MOUSEKEYS @@ -289,8 +380,8 @@ MULTIKEYHELPA MULTIKEYHELPW NCCALCSIZE_PARAMS NMHDR -# NONCLIENTMETRICSA -# NONCLIENTMETRICSW +NONCLIENTMETRICSA +NONCLIENTMETRICSW PAINTSTRUCT SCROLLINFO SERIALKEYSA @@ -303,7 +394,7 @@ TOGGLEKEYS TPMPARAMS TRACKMOUSEEVENT WINDOWINFO -WINDOWPLACEMENT +# WINDOWPLACEMENT WINDOWPOS WNDCLASSA WNDCLASSEXA diff --git a/tools/winapi/winapi_extract b/tools/winapi/winapi_extract index d89e8e7a682..b16ee8e5407 100755 --- a/tools/winapi/winapi_extract +++ b/tools/winapi/winapi_extract @@ -331,7 +331,7 @@ foreach my $file (@h_files, @c_files) { my $field_type_name = $field->type_name; my $field_name = $field->name; - if ($options->struct) { + if ($options->struct && $kind =~ /^(?:struct|union)$/) { if ($name) { $output->write("$name:$field_type_name:$field_name\n"); } else { diff --git a/tools/winapi/winapi_test b/tools/winapi/winapi_test index 1b74ab6fea8..3e7582e38cb 100755 --- a/tools/winapi/winapi_test +++ b/tools/winapi/winapi_test @@ -104,8 +104,70 @@ my %defines = ( "SIZE_OF_80387_REGISTERS" => 80, ); -my %kludge_reported = ("FILETIME" => 1, "LARGE_INTEGER" => 1); -my %parse_reported; +my %align_kludge_reported = ("FILETIME" => 1, "LARGE_INTEGER" => 1); + +sub find_align { + my $type_name = shift; + + local $_ = $type_name; + + # Remove "count" and "bits" + s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/; + + my $align; + if (0) { + # Nothing + } elsif (/\*+$/) { + $align = 4; + } elsif(/^(?:(?:signed\s+|unsigned\s+)?char)$/) { + $align = 1; + } elsif (/^(?:(?:signed\s+|unsigned\s+)?short)$/) { + $align = 2; + } elsif (/^(?:wchar_t)$/) { + $align = 2; + } elsif (/^(?:(?:signed\s+|unsigned\s+)?(?:__int32|int|long(?:\s+int)?)|unsigned|signed)$/) { + $align = 4; + } elsif (/^(?:float)$/) { + $align = 4; + } elsif (/^(?:signed\s+|unsigned\s+)?__int64$/) { + $align = 4; + } elsif (/^(?:double)$/) { + $align = 4; + } elsif (/^(?:long\s+double)$/) { + $align = 4; + } elsif (/^H(?:DC|BITMAP|BRUSH|ICON|INSTANCE|MENU|METAFILE|WND)$/) { + $align = 4; + } elsif (/^LP(?:CSTR|CWSTR|DWORD|STR|VOID|THREAD_START_ROUTINE|WSTR)$/) { + $align = 4; + } elsif (/^(?:(?:MSGBOX)CALLBACK[AW]?|(?:FAR|WND)PROC[AW]?)$/) { + $align = 4; + } elsif (/^(?:FILETIME|LARGE_INTEGER|LONGLONG)$/) { + $align = 4; + } else { + $align = undef; + } + + my $align2; + if (defined(my $type = $type_name2type{$_})) { + $align2 = $type->align; + } + + if (!defined($align)) { + $align = $align2; + } elsif (defined($align2) && !$align_kludge_reported{$_}) { + $align_kludge_reported{$_} = 1; + $output->write("$type_name: type needn't be kludged\n"); + } + + if (!defined($align)) { + # $output->write("$type_name: can't find type\n"); + } + + return $align; +} + +my %size_kludge_reported = ("FILETIME" => 1, "LARGE_INTEGER" => 1); +my %size_parse_reported; sub find_size { my $type_name = shift; @@ -148,12 +210,10 @@ sub find_size { $size = 4; } elsif (/^(?:FILETIME|LARGE_INTEGER|LONGLONG)$/) { $size = 8; - } elsif (/^(?:CRITICAL_SECTION)$/) { - $size = 24; } elsif (/^(?:struct|union)$/) { - if (!$parse_reported{$_}) { + if (!$size_parse_reported{$_}) { $output->write("$type_name: can't parse type\n"); - $parse_reported{$_} = 1; + $size_parse_reported{$_} = 1; } $size = undef; } else { @@ -167,8 +227,8 @@ sub find_size { if (!defined($size)) { $size = $size2; - } elsif (defined($size2) && !$kludge_reported{$_}) { - $kludge_reported{$_} = 1; + } elsif (defined($size2) && !$size_kludge_reported{$_}) { + $size_kludge_reported{$_} = 1; $output->write("$type_name: type needn't be kludged\n"); } @@ -246,7 +306,7 @@ foreach my $file (@files) { if (/^\#\s*include\s+\"pshpack(\d+)\.h\"$/) { push @packs, $1; } elsif(/^\#\s*include\s+\"poppack\.h\"$/) { - unshift @packs; + pop @packs; } return 1; @@ -258,23 +318,29 @@ foreach my $file (@files) { &$update_output(); - if (!defined($type->pack)) { - my $pack = $packs[$#packs]; - $type->pack($pack); - } - my $name = $type->name; $file2types{$file}{$name} = $type; - my $size = $type->size(\&find_size); + $type->set_find_align_callback(\&find_align); + $type->set_find_size_callback(\&find_size); + + my $pack = $packs[$#packs]; + if (!defined($type->pack)) { + $type->pack($pack); + } + my $size = $type->size(); if (defined($size)) { - foreach my $field ($type->fields(\&find_size)) { + my $max_field_base_size = 0; + + foreach my $field ($type->fields()) { my $field_type_name = $field->type_name; my $field_name = $field->name; my $field_size = $field->size; + my $field_base_size = $field->base_size; my $field_offset = $field->offset; + my $field_align = $field->align; - # $output->write("$name: $field_type_name: $field_name: $field_offset: $field_size\n"); + # $output->write("$name: $field_type_name: $field_name: $field_offset: $field_size($field_base_size): $field_align\n"); } # $output->write("$name: $size\n"); @@ -324,6 +390,7 @@ sub output_header { print OUT "#include \n"; print OUT "\n"; print OUT "#include \"wine/test.h\"\n"; + print OUT "#include \"wine/test_generated.h\"\n"; foreach my $test (@tests) { my @includes = $tests->get_section($test_dir, $test, "include"); foreach my $include (@includes) { @@ -377,12 +444,17 @@ sub output_test_pack { next; } $type_name_not_used{$type_name} = 0; - - my $pack = $type->pack; - print OUT " /* $type_name */\n"; + my $type_align = $type->align; + my $type_pack = $type->pack; + my $type_size = $type->size; - foreach my $field ($type->fields(\&find_size)) { + print OUT " /* $type_name (pack $type_pack) */\n"; + if (defined($type_align) && defined($type_size)) { + print OUT " TEST_TYPE($type_name, $type_size, $type_align);\n"; + } + + foreach my $field ($type->fields()) { my $field_type_name = $field->type_name; my $field_name = $field->name; my $field_size = $field->size; @@ -392,30 +464,12 @@ sub output_test_pack { 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"; - } + print OUT " TEST_FIELD($type_name, $field_type_name, $field_name, $field_offset, $field_size, $field_align);\n"; } else { $output->write("$type_name: $field_type_name: $field_name: test not generated (offset not defined)\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"); - } + print OUT "\n"; } }