- Improved alignment and offset calculations.

- Reorganized and improved enum/union/struct parsing.
This commit is contained in:
Patrik Stridvall 2002-10-11 17:53:13 +00:00 committed by Alexandre Julliard
parent 1cc2cee66f
commit 65442cd763
5 changed files with 622 additions and 320 deletions

View File

@ -696,6 +696,80 @@ sub parse_c_declarations {
return 1; 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 # parse_c_expression
@ -1502,6 +1576,104 @@ sub parse_c_statements {
return 1; 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 # parse_c_tuple
@ -1634,178 +1806,104 @@ sub parse_c_typedef {
my $refline = shift; my $refline = shift;
my $refcolumn = shift; my $refcolumn = shift;
my $reftype = shift;
local $_ = $$refcurrent; local $_ = $$refcurrent;
my $line = $$refline; my $line = $$refline;
my $column = $$refcolumn; my $column = $$refcolumn;
my $type; my $type;
if (0) { if (!$self->_parse_c("typedef", \$_, \$line, \$column)) {
return 0;
}
my $finished = 0;
if ($finished) {
# Nothing # Nothing
} elsif (s/^(?:typedef\s+)?(enum\s+|struct\s+|union\s+)((?:MSVCRT|WS)\(\s*\w+\s*\)|\w+)?\s*\{\s*//s) { } elsif ($self->parse_c_enum(\$_, \$line, \$column)) {
$self->_update_c_position($&, \$line, \$column); $finished = 1;
}
my $kind = $1; my $kind;
my $_name = $2 || ""; my $_name;
my @field_type_names;
$kind =~ s/\s+//g; my @field_names;
my @names;
if ($kind =~ /^struct|union$/) { if ($finished) {
my $name = ""; # Nothing
my @field_type_names = (); } elsif ($self->parse_c_struct_union(\$_, \$line, \$column,
my @field_names = (); \$kind, \$_name, \@field_type_names, \@field_names, \@names))
{
my $match; my $base_name;
while ($_ && $self->_parse_c_on_same_level_until_one_of(';', \$_, \$line, \$column, \$match)) foreach my $name (@names) {
{ if ($name =~ /^\w+$/) {
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 $type = &$$create_type(); my $type = &$$create_type();
if (length($name) == 0) { $type->kind($kind);
$self->_parse_c_error($_, $line, $column, "typedef"); $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->kind("");
$type->name($name); $type->name($name);
$type->pack(1);
$type->field_type_names([$type_name]); $type->field_type_names([$type_name]);
$type->field_names([""]); $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 && $_ && !/^,/) { $type->kind("");
$self->_parse_c_error($_, $line, $column, "typedef"); $type->name($name);
} $type->field_type_names([$type_name]);
} else { $type->field_names([""]);
$self->_parse_c_error($_, $line, $column, "typedef");
&$$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 { } else {
return 0; $self->_parse_c_error($_, $line, $column, "typedef");
} }
$$refcurrent = $_; $$refcurrent = $_;
$$refline = $line; $$refline = $line;
$$refcolumn = $column; $$refcolumn = $column;
$$reftype = $type;
return 1; return 1;
} }
@ -1860,7 +1958,7 @@ sub parse_c_variable {
# Nothing # Nothing
} elsif(/^$/) { } elsif(/^$/) {
return 0; 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 $kind = $1;
my $_name = $2; my $_name = $2;
$self->_update_c_position($&, \$line, \$column); $self->_update_c_position($&, \$line, \$column);

View File

@ -31,13 +31,36 @@ sub new {
return $self; 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 { sub kind {
my $self = shift; my $self = shift;
my $kind = \${$self->{KIND}}; my $kind = \${$self->{KIND}};
my $dirty = \${$self->{DIRTY}};
local $_ = shift; local $_ = shift;
if(defined($_)) { $$kind = $_; } if(defined($_)) { $$kind = $_; $$dirty = 1; }
return $$kind; return $$kind;
} }
@ -45,10 +68,11 @@ sub kind {
sub _name { sub _name {
my $self = shift; my $self = shift;
my $_name = \${$self->{_NAME}}; my $_name = \${$self->{_NAME}};
my $dirty = \${$self->{DIRTY}};
local $_ = shift; local $_ = shift;
if(defined($_)) { $$_name = $_; } if(defined($_)) { $$_name = $_; $$dirty = 1; }
return $$_name; return $$_name;
} }
@ -56,10 +80,11 @@ sub _name {
sub name { sub name {
my $self = shift; my $self = shift;
my $name = \${$self->{NAME}}; my $name = \${$self->{NAME}};
my $dirty = \${$self->{DIRTY}};
local $_ = shift; local $_ = shift;
if(defined($_)) { $$name = $_; } if(defined($_)) { $$name = $_; $$dirty = 1; }
if($$name) { if($$name) {
return $$name; return $$name;
@ -74,22 +99,27 @@ sub name {
sub pack { sub pack {
my $self = shift; my $self = shift;
my $pack = \${$self->{PACK}}; my $pack = \${$self->{PACK}};
my $dirty = \${$self->{DIRTY}};
local $_ = shift; local $_ = shift;
if(defined($_)) { $$pack = $_; } if(defined($_)) { $$pack = $_; $$dirty = 1; }
return $$pack; return $$pack;
} }
sub fields { sub align {
my $self = shift; my $self = shift;
my $find_size = shift; my $align = \${$self->{ALIGN}};
if (defined($find_size)) { $self->_refresh();
$self->_refresh($find_size);
} return $$align;
}
sub fields {
my $self = shift;
my $count = $self->field_count; my $count = $self->field_count;
@ -101,15 +131,20 @@ sub fields {
return @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 { sub field_aligns {
my $self = shift; my $self = shift;
my $field_aligns = \${$self->{FIELD_ALIGNS}}; my $field_aligns = \${$self->{FIELD_ALIGNS}};
my $find_size = shift; $self->_refresh();
if (defined($find_size)) {
$self->_refresh($find_size);
}
return $$field_aligns; return $$field_aligns;
} }
@ -127,10 +162,11 @@ sub field_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}};
my $dirty = \${$self->{DIRTY}};
local $_ = shift; local $_ = shift;
if(defined($_)) { $$field_names = $_; } if(defined($_)) { $$field_names = $_; $$dirty = 1; }
return $$field_names; return $$field_names;
} }
@ -139,11 +175,7 @@ sub field_offsets {
my $self = shift; my $self = shift;
my $field_offsets = \${$self->{FIELD_OFFSETS}}; my $field_offsets = \${$self->{FIELD_OFFSETS}};
my $find_size = shift; $self->_refresh();
if (defined($find_size)) {
$self->_refresh($find_size);
}
return $$field_offsets; return $$field_offsets;
} }
@ -152,11 +184,7 @@ sub field_sizes {
my $self = shift; my $self = shift;
my $field_sizes = \${$self->{FIELD_SIZES}}; my $field_sizes = \${$self->{FIELD_SIZES}};
my $find_size = shift; $self->_refresh();
if (defined($find_size)) {
$self->_refresh($find_size);
}
return $$field_sizes; return $$field_sizes;
} }
@ -164,10 +192,11 @@ sub field_sizes {
sub field_type_names { sub field_type_names {
my $self = shift; my $self = shift;
my $field_type_names = \${$self->{FIELD_TYPE_NAMES}}; my $field_type_names = \${$self->{FIELD_TYPE_NAMES}};
my $dirty = \${$self->{DIRTY}};
local $_ = shift; local $_ = shift;
if(defined($_)) { $$field_type_names = $_; } if(defined($_)) { $$field_type_names = $_; $$dirty = 1; }
return $$field_type_names; return $$field_type_names;
} }
@ -177,10 +206,7 @@ sub size {
my $size = \${$self->{SIZE}}; my $size = \${$self->{SIZE}};
my $find_size = shift; $self->_refresh();
if (defined($find_size)) {
$self->_refresh($find_size);
}
return $$size; return $$size;
} }
@ -188,36 +214,52 @@ sub size {
sub _refresh { sub _refresh {
my $self = shift; 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_aligns = \${$self->{FIELD_ALIGNS}};
my $field_base_sizes = \${$self->{FIELD_BASE_SIZES}};
my $field_offsets = \${$self->{FIELD_OFFSETS}}; my $field_offsets = \${$self->{FIELD_OFFSETS}};
my $field_sizes = \${$self->{FIELD_SIZES}}; my $field_sizes = \${$self->{FIELD_SIZES}};
my $size = \${$self->{SIZE}};
my $find_size = shift;
my $pack = $self->pack; my $pack = $self->pack;
my $max_field_align = 0;
my $offset = 0; my $offset = 0;
my $offset_bits = 0; my $offset_bits = 0;
my $n = 0; my $n = 0;
foreach my $field ($self->fields) { foreach my $field ($self->fields) {
my $type_name = $field->type_name; my $type_name = $field->type_name;
my $size = &$find_size($type_name); my $size = &$$find_size($type_name);
my $base_type_name = $type_name; my $base_type_name = $type_name;
if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) { if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) {
my $count = $2; my $count = $2;
my $bits = $3; 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; if (defined($align)) {
$align = $base_size % 4 if defined($base_size); $align = $pack if $align > $pack;
$align = 4 if !$align; $max_field_align = $align if $align > $max_field_align;
if ($offset % $align != 0) {
$offset = (int($offset / $align) + 1) * $align;
}
}
if (!defined($size)) { if (!defined($size)) {
$$align = undef;
$$size = undef; $$size = undef;
return; return;
} elsif ($size >= 0) { } elsif ($size >= 0) {
@ -227,12 +269,14 @@ sub _refresh {
} }
$$$field_aligns[$n] = $align; $$$field_aligns[$n] = $align;
$$$field_base_sizes[$n] = $base_size;
$$$field_offsets[$n] = $offset; $$$field_offsets[$n] = $offset;
$$$field_sizes[$n] = $size; $$$field_sizes[$n] = $size;
$offset += $size; $offset += $size;
} else { } else {
$$$field_aligns[$n] = $align; $$$field_aligns[$n] = $align;
$$$field_base_sizes[$n] = $base_size;
$$$field_offsets[$n] = $offset; $$$field_offsets[$n] = $offset;
$$$field_sizes[$n] = $size; $$$field_sizes[$n] = $size;
@ -242,12 +286,17 @@ sub _refresh {
$n++; $n++;
} }
$$align = $pack;
$$align = $max_field_align if $max_field_align < $pack;
$$size = $offset; $$size = $offset;
if (1) { if ($$kind =~ /^(?:struct|union)$/) {
if ($$size % $pack != 0) { if ($$size % $$align != 0) {
$$size = (int($$size / $pack) + 1) * $pack; $$size = (int($$size / $$align) + 1) * $$align;
} }
} }
$$dirty = 0;
} }
package c_type_field; package c_type_field;
@ -277,6 +326,16 @@ sub align {
return $$field_aligns[$$number]; 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 { sub name {
my $self = shift; my $self = shift;
my $type = \${$self->{TYPE}}; my $type = \${$self->{TYPE}};

View File

@ -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 %%%dlls/gdi/tests
%%pack %%pack
@ -102,10 +44,10 @@ EMRARC
EMRBITBLT EMRBITBLT
EMRCREATEBRUSHINDIRECT EMRCREATEBRUSHINDIRECT
EMRCREATECOLORSPACE EMRCREATECOLORSPACE
# EMRCREATECOLORSPACEW EMRCREATECOLORSPACEW
EMRCREATEDIBPATTERNBRUSHPT EMRCREATEDIBPATTERNBRUSHPT
EMRCREATEMONOBRUSH EMRCREATEMONOBRUSH
EMRCREATEPALETTE # EMRCREATEPALETTE
EMRCREATEPEN EMRCREATEPEN
EMRDELETECOLORSPACE EMRDELETECOLORSPACE
EMRDELETEOBJECT EMRDELETEOBJECT
@ -115,23 +57,23 @@ EMREXCLUDECLIPRECT
EMREXTCREATEFONTINDIRECTW EMREXTCREATEFONTINDIRECTW
EMREXTCREATEPEN EMREXTCREATEPEN
EMREXTFLOODFILL EMREXTFLOODFILL
# EMREXTSELECTCLIPRGN EMREXTSELECTCLIPRGN
EMREXTTEXTOUTA EMREXTTEXTOUTA
EMRFILLPATH EMRFILLPATH
# EMRFILLRGN EMRFILLRGN
EMRFORMAT EMRFORMAT
# EMRFRAMERGN EMRFRAMERGN
# EMRGDICOMMENT EMRGDICOMMENT
# EMRGLSBOUNDEDRECORD EMRGLSBOUNDEDRECORD
# EMRGLSRECORD EMRGLSRECORD
# EMRINVERTRGN EMRINVERTRGN
EMRLINETO EMRLINETO
EMRMASKBLT EMRMASKBLT
EMRMODIFYWORLDTRANSFORM EMRMODIFYWORLDTRANSFORM
EMROFFSETCLIPRGN EMROFFSETCLIPRGN
EMRPIXELFORMAT EMRPIXELFORMAT
EMRPLGBLT EMRPLGBLT
# EMRPOLYDRAW EMRPOLYDRAW
EMRPOLYLINE EMRPOLYLINE
EMRPOLYPOLYLINE EMRPOLYPOLYLINE
EMRPOLYTEXTOUTA EMRPOLYTEXTOUTA
@ -148,7 +90,7 @@ EMRSETCOLORADJUSTMENT
EMRSETDIBITSTODEIVCE EMRSETDIBITSTODEIVCE
EMRSETMAPPERFLAGS EMRSETMAPPERFLAGS
EMRSETMITERLIMIT EMRSETMITERLIMIT
EMRSETPALETTEENTRIES # EMRSETPALETTEENTRIES
EMRSETPIXELV EMRSETPIXELV
EMRSETTEXTJUSTIFICATION EMRSETTEXTJUSTIFICATION
EMRSETVIEWPORTEXTEX EMRSETVIEWPORTEXTEX
@ -180,29 +122,29 @@ LOGCOLORSPACEA
LOGCOLORSPACEW LOGCOLORSPACEW
LOGFONTA LOGFONTA
LOGFONTW LOGFONTW
LOGPALETTE # LOGPALETTE
LOGPEN LOGPEN
MAT2 MAT2
METAFILEPICT METAFILEPICT
METAHEADER METAHEADER
METARECORD METARECORD
# NEWTEXTMETRICA NEWTEXTMETRICA
NEWTEXTMETRICEXA NEWTEXTMETRICEXA
NEWTEXTMETRICEXW NEWTEXTMETRICEXW
# NEWTEXTMETRICW NEWTEXTMETRICW
# OUTLINETEXTMETRICA OUTLINETEXTMETRICA
# OUTLINETEXTMETRICW OUTLINETEXTMETRICW
PALETTEENTRY # PALETTEENTRY
# PANOSE PANOSE
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
@ -211,6 +153,154 @@ TTPOLYCURVE
TTPOLYGONHEADER TTPOLYGONHEADER
XFORM 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 %%%dlls/user/tests
%%pack %%pack
@ -225,11 +315,12 @@ basetsd.h
winnt.h winnt.h
windef.h windef.h
winbase.h winbase.h
wingdi.h
winuser.h winuser.h
%struct %struct
# ACCEL ACCEL
ACCESSTIMEOUT ACCESSTIMEOUT
ANIMATIONINFO ANIMATIONINFO
CBTACTIVATESTRUCT CBTACTIVATESTRUCT
@ -247,7 +338,7 @@ DEBUGHOOKINFO
DELETEITEMSTRUCT DELETEITEMSTRUCT
DLGITEMTEMPLATE DLGITEMTEMPLATE
DLGTEMPLATE DLGTEMPLATE
DRAWITEMSTRUCT # DRAWITEMSTRUCT
DRAWTEXTPARAMS DRAWTEXTPARAMS
EVENTMSG EVENTMSG
FILTERKEYS FILTERKEYS
@ -259,9 +350,9 @@ HELPWININFOW
HIGHCONTRASTA HIGHCONTRASTA
HIGHCONTRASTW HIGHCONTRASTW
ICONINFO ICONINFO
# ICONMETRICSA ICONMETRICSA
# ICONMETRICSW ICONMETRICSW
# INPUT INPUT
KBDLLHOOKSTRUCT KBDLLHOOKSTRUCT
KEYBDINPUT KEYBDINPUT
MDICREATESTRUCTA MDICREATESTRUCTA
@ -271,13 +362,13 @@ MEASUREITEMSTRUCT
MENUINFO MENUINFO
MENUITEMINFOA MENUITEMINFOA
MENUITEMINFOW MENUITEMINFOW
# MENUITEMTEMPLATE MENUITEMTEMPLATE
MENUITEMTEMPLATEHEADER MENUITEMTEMPLATEHEADER
MINIMIZEDMETRICS MINIMIZEDMETRICS
MINMAXINFO MINMAXINFO
MONITORINFO MONITORINFO
# MONITORINFOEXA MONITORINFOEXA
# MONITORINFOEXW MONITORINFOEXW
MOUSEHOOKSTRUCT MOUSEHOOKSTRUCT
MOUSEINPUT MOUSEINPUT
MOUSEKEYS MOUSEKEYS
@ -289,8 +380,8 @@ MULTIKEYHELPA
MULTIKEYHELPW MULTIKEYHELPW
NCCALCSIZE_PARAMS NCCALCSIZE_PARAMS
NMHDR NMHDR
# NONCLIENTMETRICSA NONCLIENTMETRICSA
# NONCLIENTMETRICSW NONCLIENTMETRICSW
PAINTSTRUCT PAINTSTRUCT
SCROLLINFO SCROLLINFO
SERIALKEYSA SERIALKEYSA
@ -303,7 +394,7 @@ TOGGLEKEYS
TPMPARAMS TPMPARAMS
TRACKMOUSEEVENT TRACKMOUSEEVENT
WINDOWINFO WINDOWINFO
WINDOWPLACEMENT # WINDOWPLACEMENT
WINDOWPOS WINDOWPOS
WNDCLASSA WNDCLASSA
WNDCLASSEXA WNDCLASSEXA

View File

@ -331,7 +331,7 @@ foreach my $file (@h_files, @c_files) {
my $field_type_name = $field->type_name; my $field_type_name = $field->type_name;
my $field_name = $field->name; my $field_name = $field->name;
if ($options->struct) { if ($options->struct && $kind =~ /^(?:struct|union)$/) {
if ($name) { if ($name) {
$output->write("$name:$field_type_name:$field_name\n"); $output->write("$name:$field_type_name:$field_name\n");
} else { } else {

View File

@ -104,8 +104,70 @@ my %defines = (
"SIZE_OF_80387_REGISTERS" => 80, "SIZE_OF_80387_REGISTERS" => 80,
); );
my %kludge_reported = ("FILETIME" => 1, "LARGE_INTEGER" => 1); my %align_kludge_reported = ("FILETIME" => 1, "LARGE_INTEGER" => 1);
my %parse_reported;
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 { sub find_size {
my $type_name = shift; my $type_name = shift;
@ -148,12 +210,10 @@ sub find_size {
$size = 4; $size = 4;
} elsif (/^(?:FILETIME|LARGE_INTEGER|LONGLONG)$/) { } elsif (/^(?:FILETIME|LARGE_INTEGER|LONGLONG)$/) {
$size = 8; $size = 8;
} elsif (/^(?:CRITICAL_SECTION)$/) {
$size = 24;
} elsif (/^(?:struct|union)$/) { } elsif (/^(?:struct|union)$/) {
if (!$parse_reported{$_}) { if (!$size_parse_reported{$_}) {
$output->write("$type_name: can't parse type\n"); $output->write("$type_name: can't parse type\n");
$parse_reported{$_} = 1; $size_parse_reported{$_} = 1;
} }
$size = undef; $size = undef;
} else { } else {
@ -167,8 +227,8 @@ sub find_size {
if (!defined($size)) { if (!defined($size)) {
$size = $size2; $size = $size2;
} elsif (defined($size2) && !$kludge_reported{$_}) { } elsif (defined($size2) && !$size_kludge_reported{$_}) {
$kludge_reported{$_} = 1; $size_kludge_reported{$_} = 1;
$output->write("$type_name: type needn't be kludged\n"); $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\"$/) { if (/^\#\s*include\s+\"pshpack(\d+)\.h\"$/) {
push @packs, $1; push @packs, $1;
} elsif(/^\#\s*include\s+\"poppack\.h\"$/) { } elsif(/^\#\s*include\s+\"poppack\.h\"$/) {
unshift @packs; pop @packs;
} }
return 1; return 1;
@ -258,23 +318,29 @@ foreach my $file (@files) {
&$update_output(); &$update_output();
if (!defined($type->pack)) {
my $pack = $packs[$#packs];
$type->pack($pack);
}
my $name = $type->name; my $name = $type->name;
$file2types{$file}{$name} = $type; $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)) { 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_type_name = $field->type_name;
my $field_name = $field->name; my $field_name = $field->name;
my $field_size = $field->size; my $field_size = $field->size;
my $field_base_size = $field->base_size;
my $field_offset = $field->offset; 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"); # $output->write("$name: $size\n");
@ -324,6 +390,7 @@ sub output_header {
print OUT "#include <stdio.h>\n"; print OUT "#include <stdio.h>\n";
print OUT "\n"; print OUT "\n";
print OUT "#include \"wine/test.h\"\n"; print OUT "#include \"wine/test.h\"\n";
print OUT "#include \"wine/test_generated.h\"\n";
foreach my $test (@tests) { foreach my $test (@tests) {
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) {
@ -377,12 +444,17 @@ sub output_test_pack {
next; next;
} }
$type_name_not_used{$type_name} = 0; $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_type_name = $field->type_name;
my $field_name = $field->name; my $field_name = $field->name;
my $field_size = $field->size; my $field_size = $field->size;
@ -392,30 +464,12 @@ sub output_test_pack {
next if $field_name eq "" || (defined($field_size) && $field_size < 0); next if $field_name eq "" || (defined($field_size) && $field_size < 0);
if (defined($field_size) && defined($field_offset)) { if (defined($field_size) && defined($field_offset)) {
print OUT " ok(FIELD_OFFSET($type_name, $field_name) == $field_offset,\n"; print OUT " TEST_FIELD($type_name, $field_type_name, $field_name, $field_offset, $field_size, $field_align);\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";
}
} else { } else {
$output->write("$type_name: $field_type_name: $field_name: test not generated (offset not defined)\n"); $output->write("$type_name: $field_type_name: $field_name: test not generated (offset not defined)\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");
}
} }
} }