Reorganized the code for better support of data structures parsing.
This commit is contained in:
parent
7bdf2ff9f4
commit
91a3686853
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
my $pack = $packs[$#packs];
|
&$update_output();
|
||||||
$type->pack($pack);
|
|
||||||
|
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;
|
||||||
|
|
||||||
&$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;
|
||||||
|
|
||||||
|
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 {
|
} 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;
|
|
||||||
|
|
||||||
print OUT " ok(sizeof($type_name) == $type_size, ";
|
if (defined($type_size)) {
|
||||||
print OUT "\"sizeof($type_name) == %d (expected $type_size)\", ";
|
print OUT " ok(sizeof($type_name) == $type_size, ";
|
||||||
print OUT "sizeof($type_name));\n";
|
print OUT "\"sizeof($type_name) == %d (expected $type_size)\", ";
|
||||||
print OUT "\n";
|
print OUT "sizeof($type_name));\n";
|
||||||
|
print OUT "\n";
|
||||||
|
} else {
|
||||||
|
$output->write("$type_name: test not generated (size not defined)\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue