Several bug fixes and additions.

This commit is contained in:
Patrik Stridvall 2001-07-08 20:33:20 +00:00 committed by Alexandre Julliard
parent 14e690f47f
commit 47a99e1a78
15 changed files with 612 additions and 343 deletions

View File

@ -119,7 +119,7 @@ sub translate_calling_convention16 {
if(/^__cdecl$/) { if(/^__cdecl$/) {
return "cdecl"; return "cdecl";
} elsif(/^VFWAPIV|WINAPIV$/) { } elsif(/^VFWAPIV|WINAPIV$/) {
return "varargs"; return "pascal"; # FIXME: Is this correct?
} elsif(/^__stdcall|VFWAPI|WINAPI|CALLBACK$/) { } elsif(/^__stdcall|VFWAPI|WINAPI|CALLBACK$/) {
return "pascal"; return "pascal";
} elsif(/^__asm$/) { } elsif(/^__asm$/) {

View File

@ -118,23 +118,54 @@ foreach my $file (@files) {
local $_; local $_;
foreach (split(/\n/, $documentation)) { foreach (split(/\n/, $documentation)) {
if(/^\s*\*\s*(\w+|\@)\s*[\(\[]\s*(\w+)\s*\.\s*(\@|\d+)\s*[\)\]]/) { if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*(\S+)\s*[\)\]]/) {
my $external_name = $1; my $external_name = $1;
my $module = lc($2); my $module = lc($2);
my $ordinal = $3; my $ordinal = $3;
if($ordinal eq "@") { if($ordinal eq "@") {
$specifications{$module}{unfixed}{$external_name}{debug_channels} = [@debug_channels]; if(1 || !exists($specifications{$module}{unfixed}{$external_name})) {
$specifications{$module}{unfixed}{$external_name}{internal_name} = $internal_name; $specifications{$module}{unfixed}{$external_name}{debug_channels} = [@debug_channels];
$specifications{$module}{unfixed}{$external_name}{external_name} = $external_name; $specifications{$module}{unfixed}{$external_name}{internal_name} = $internal_name;
$specifications{$module}{unfixed}{$external_name}{ordinal} = $ordinal; $specifications{$module}{unfixed}{$external_name}{external_name} = $external_name;
$specifications{$module}{unfixed}{$external_name}{arguments} = [@argument_types]; $specifications{$module}{unfixed}{$external_name}{ordinal} = $ordinal;
$specifications{$module}{unfixed}{$external_name}{return_type} = $return_type;
$specifications{$module}{unfixed}{$external_name}{argument_types} = [@argument_types];
} else {
output->write("$file: $external_name ($module.$ordinal) already exists\n");
}
} elsif($ordinal =~ /^\d+$/) {
if(1 || !exists($specifications{$module}{fixed}{$ordinal})) {
$specifications{$module}{fixed}{$ordinal}{debug_channels} = [@debug_channels];
$specifications{$module}{fixed}{$ordinal}{ordinal} = $ordinal;
$specifications{$module}{fixed}{$ordinal}{internal_name} = $internal_name;
$specifications{$module}{fixed}{$ordinal}{external_name} = $external_name;
$specifications{$module}{fixed}{$ordinal}{return_type} = $return_type;
$specifications{$module}{fixed}{$ordinal}{argument_types} = [@argument_types];
} else {
output->write("$file: $external_name ($module.$ordinal) already exists\n");
}
} elsif($ordinal eq "init") {
if(!exists($specifications{$module}{init})) {
$specifications{$module}{init}{debug_channels} = [@debug_channels];
$specifications{$module}{init}{external_name} = $external_name;
$specifications{$module}{init}{internal_name} = $internal_name;
$specifications{$module}{init}{return_type} = $return_type;
$specifications{$module}{init}{argument_types} = [@argument_types];
} else {
output->write("$file: $external_name ($module.$ordinal) already exists\n");
}
} else { } else {
$specifications{$module}{fixed}{$ordinal}{debug_channels} = [@debug_channels]; if(!exists($specifications{$module}{unknown}{$external_name})) {
$specifications{$module}{fixed}{$ordinal}{ordinal} = $ordinal; $specifications{$module}{unknown}{$external_name}{debug_channels} = [@debug_channels];
$specifications{$module}{fixed}{$ordinal}{internal_name} = $internal_name; $specifications{$module}{unknown}{$external_name}{internal_name} = $internal_name;
$specifications{$module}{fixed}{$ordinal}{external_name} = $external_name; $specifications{$module}{unknown}{$external_name}{external_name} = $external_name;
$specifications{$module}{fixed}{$ordinal}{arguments} = [@argument_types]; $specifications{$module}{unknown}{$external_name}{ordinal} = $ordinal;
$specifications{$module}{unknown}{$external_name}{return_type} = $return_type;
$specifications{$module}{unknown}{$external_name}{argument_types} = [@argument_types];
} else {
output->write("$file: $external_name ($module.$ordinal) already exists\n");
}
} }
if($options->debug) { if($options->debug) {
@ -165,32 +196,52 @@ sub output_function {
my $internal_name = $function->{internal_name}; my $internal_name = $function->{internal_name};
my $external_name = $function->{external_name}; my $external_name = $function->{external_name};
my $ordinal = $function->{ordinal}; my $ordinal = $function->{ordinal};
my @arguments = @{$function->{arguments}}; my $return_type = $function->{return_type};
my @argument_types = @{$function->{argument_types}};
my @arguments2;
foreach my $argument (@arguments) {
my $argument2;
if($type eq "win16") {
$argument2 = $win16api->translate_argument($argument);
} else {
$argument2 = $win32api->translate_argument($argument);
}
if(!defined($argument2)) {
$argument2 = "undef";
}
if($argument2 eq "longlong") {
push @arguments2, ("long", "long");
} else {
push @arguments2, $argument2;
}
}
my $return_kind;
if($type eq "win16") { if($type eq "win16") {
print OUT "$ordinal pascal $external_name(@arguments2) $internal_name\n"; $return_kind = $win16api->translate_argument($return_type);
} else { } else {
print OUT "$ordinal stdcall $external_name(@arguments2) $internal_name\n"; $return_kind = $win32api->translate_argument($return_type);
} }
if(!defined($return_kind)) {
$return_kind = "undef";
}
my @argument_kinds;
foreach my $argument_kind (@argument_kinds) {
my $argument_kind;
if($type eq "win16") {
$argument_kind = $win16api->translate_argument($argument_kind);
} else {
$argument_kind = $win32api->translate_argument($argument_kind);
}
if(!defined($argument_kind)) {
$argument_kind = "undef";
}
if($argument_kind eq "longlong") {
push @argument_kinds, ("long", "long");
} else {
push @argument_kinds, $argument_kind;
}
}
my $calling_convention;
if($type eq "win16") {
if($return_kind =~ /^(?:void|s_word|word)$/) {
$calling_convention = "pascal16";
} elsif($return_kind =~ /^(?:long|ptr|segptr|segstr|str|wstr)$/) {
$calling_convention = "pascal";
} else {
$calling_convention = "undef";
}
} else {
$calling_convention = "stdcall";
}
print OUT "$ordinal $calling_convention $external_name(@argument_kinds) $internal_name\n";
} }
if($options->spec_files) { if($options->spec_files) {
@ -210,9 +261,19 @@ if($options->spec_files) {
print OUT "name $module\n"; print OUT "name $module\n";
print OUT "type $type\n"; print OUT "type $type\n";
if(exists($specifications{$module}{init})) {
my $init = $specifications{$module}{init}{internal_name};
print OUT "init $init\n";
}
print OUT "\n"; print OUT "\n";
my %debug_channels; my %debug_channels;
if(exists($specifications{$module}{init})) {
my $function = $specifications{$module}{init};
foreach my $debug_channel (@{$function->{debug_channels}}) {
$debug_channels{$debug_channel}++;
}
}
foreach my $ordinal (sort {$a <=> $b} keys(%{$specifications{$module}{fixed}})) { foreach my $ordinal (sort {$a <=> $b} keys(%{$specifications{$module}{fixed}})) {
my $function = $specifications{$module}{fixed}{$ordinal}; my $function = $specifications{$module}{fixed}{$ordinal};
foreach my $debug_channel (@{$function->{debug_channels}}) { foreach my $debug_channel (@{$function->{debug_channels}}) {
@ -225,6 +286,12 @@ if($options->spec_files) {
$debug_channels{$debug_channel}++; $debug_channels{$debug_channel}++;
} }
} }
foreach my $name (sort(keys(%{$specifications{$module}{unknown}}))) {
my $function = $specifications{$module}{unknown}{$name};
foreach my $debug_channel (@{$function->{debug_channels}}) {
$debug_channels{$debug_channel}++;
}
}
my @debug_channels = sort(keys(%debug_channels)); my @debug_channels = sort(keys(%debug_channels));
if($#debug_channels >= 0) { if($#debug_channels >= 0) {
@ -233,20 +300,38 @@ if($options->spec_files) {
} }
my $empty = 1; my $empty = 1;
foreach my $ordinal (sort {$a <=> $b} keys(%{$specifications{$module}{fixed}})) {
if(!$empty) {
print OUT "\n";
$empty = 1;
}
foreach my $name (sort(keys(%{$specifications{$module}{unknown}}))) {
my $function = $specifications{$module}{unknown}{$name};
print OUT "# ";
output_function(\*OUT, $type, $function);
$empty = 0;
}
if(!$empty) {
print OUT "\n";
$empty = 1;
}
foreach my $ordinal (sort {$a <=> $b} keys(%{$specifications{$module}{fixed}})) {
my $function = $specifications{$module}{fixed}{$ordinal}; my $function = $specifications{$module}{fixed}{$ordinal};
output_function(\*OUT, $type, $function); output_function(\*OUT, $type, $function);
$empty = 0; $empty = 0;
} }
if(!$empty) {
print OUT "\n";
$empty = 1;
}
foreach my $name (sort(keys(%{$specifications{$module}{unfixed}}))) { foreach my $name (sort(keys(%{$specifications{$module}{unfixed}}))) {
if(!$empty) {
print OUT "\n";
$empty = 1;
}
my $function = $specifications{$module}{unfixed}{$name}; my $function = $specifications{$module}{unfixed}{$name};
output_function(\*OUT, $type, $function); output_function(\*OUT, $type, $function);
$empty = 0;
} }
close(OUT); close(OUT);
} }
} }

View File

@ -38,9 +38,10 @@ my %options_long = (
"local" => { default => 1, description => "local fixup" }, "local" => { default => 1, description => "local fixup" },
"documentation" => { default => 1, parent => "local", description => "documentation fixup" }, "documentation" => { default => 1, parent => "local", description => "documentation fixup" },
"documentation-ordinal" => { default => 1, parent => "documentation", description => "documentation ordinal fixup" }, "documentation-missing" => { default => 1, parent => "documentation", description => "documentation missing fixup" },
"documentation-missing" => { default => 0, parent => "documentation", description => "documentation missing fixup" },
"documentation-name" => { default => 1, parent => "documentation", description => "documentation name fixup" }, "documentation-name" => { default => 1, parent => "documentation", description => "documentation name fixup" },
"documentation-ordinal" => { default => 1, parent => "documentation", description => "documentation ordinal fixup" },
"documentation-wrong" => { default => 1, parent => "documentation", description => "documentation wrong fixup" },
"stub" => { default => 0, parent => "local", description => "stub fixup" }, "stub" => { default => 0, parent => "local", description => "stub fixup" },
"global" => { default => 1, description => "global fixup" }, "global" => { default => 1, description => "global fixup" },
@ -71,82 +72,6 @@ if($wine_dir eq ".") {
winapi->read_spec_files($modules, $wine_dir, $current_dir, \@spec_files, $win16api, $win32api); winapi->read_spec_files($modules, $wine_dir, $current_dir, \@spec_files, $win16api, $win32api);
} }
sub get_all_module_internal_ordinal {
my $internal_name = shift;
my @entries = ();
foreach my $winapi (@winapis) {
my @name = (); {
my $name = $winapi->function_external_name($internal_name);
if(defined($name)) {
@name = split(/ & /, $name);
}
}
my @module = (); {
my $module = $winapi->function_internal_module($internal_name);
if(defined($module)) {
@module = split(/ & /, $module);
}
}
my @ordinal = (); {
my $ordinal = $winapi->function_internal_ordinal($internal_name);
if(defined($ordinal)) {
@ordinal = split(/ & /, $ordinal);
}
}
my $name;
my $module;
my $ordinal;
while(defined($name = shift @name) &&
defined($module = shift @module) &&
defined($ordinal = shift @ordinal))
{
push @entries, [$name, $module, $ordinal];
}
}
return @entries;
}
sub get_all_module_external_ordinal {
my $external_name = shift;
my @entries = ();
foreach my $winapi (@winapis) {
my @name = (); {
my $name = $winapi->function_internal_name($external_name);
if(defined($name)) {
@name = split(/ & /, $name);
}
}
my @module = (); {
my $module = $winapi->function_external_module($external_name);
if(defined($module)) {
@module = split(/ & /, $module);
}
}
my @ordinal = (); {
my $ordinal = $winapi->function_external_ordinal($external_name);
if(defined($ordinal)) {
@ordinal = split(/ & /, $ordinal);
}
}
my $name;
my $module;
my $ordinal;
while(defined($name = shift @name) &&
defined($module = shift @module) &&
defined($ordinal = shift @ordinal))
{
push @entries, [$name, $module, $ordinal];
}
}
return @entries;
}
sub normalize_set { sub normalize_set {
local $_ = shift; local $_ = shift;
@ -171,8 +96,9 @@ my $progress_current = 0;
my $progress_max = scalar(@c_files); my $progress_max = scalar(@c_files);
foreach my $file (@c_files) { foreach my $file (@c_files) {
my %substitute_line;
my %insert_line; my %insert_line;
my %substitute_line;
my %delete_line;
my %spec_file; my %spec_file;
@ -236,19 +162,109 @@ foreach my $file (@c_files) {
my $calling_convention16 = translate_calling_convention16($calling_convention); my $calling_convention16 = translate_calling_convention16($calling_convention);
my $calling_convention32 = translate_calling_convention32($calling_convention); my $calling_convention32 = translate_calling_convention32($calling_convention);
my $documention_modified = 0; my $spec_modified = 0;
if(($documentation && !$documention_modified) && if(options->stub && $documentation) {
(options->documentation_name || options->documentation_ordinal)) foreach my $winapi (@winapis) {
my @entries = ();
if($winapi->function_stub($internal_name)) {
my $module = $winapi->function_internal_module($internal_name);
my $ordinal = $winapi->function_internal_ordinal($internal_name);
my $external_name = $internal_name;
if($winapi->name eq "win16") {
$external_name =~ s/(?:_)?16([AW]?)$//;
if(defined($1)) {
$external_name .= $1;
}
}
push @entries, [$external_name, $module, $ordinal];
}
foreach (split(/\n/, $documentation)) {
if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
my $external_name = $1;
my $module = lc($2);
my $ordinal = $3;
if($external_name ne "@" &&
$winapi->is_module($module) &&
$winapi->function_stub($external_name) &&
$internal_name !~ /^\U$module\E_\Q$external_name\E$/)
{
push @entries, [$external_name, $module, $ordinal];
}
}
}
foreach my $entry (@entries) {
(my $external_name, my $module, my $ordinal) = @$entry;
my $abort = 0;
my $n;
my @argument_kinds = map {
my $type = $_;
my $kind;
if($type ne "..." && !defined($kind = $winapi->translate_argument($type))) {
output->write("no translation defined: " . $type . "\n");
}
# FIXME: Kludge
if(defined($kind) && $kind eq "longlong") {
$n += 2;
("long", "long");
} elsif(defined($kind)) {
$n++;
$kind;
} elsif($type eq "...") {
if($winapi->name eq "win16") {
$calling_convention16 = "pascal"; # FIXME: Is this correct?
} else {
$calling_convention32 = "varargs";
}
();
} else {
$abort = 1;
$n++;
"undef";
}
} @argument_types;
my $substitute = {};
$substitute->{search} = "^\\s*$ordinal\\s+stub\\s+$external_name\\s*(?:#.*?)?\$";
if($winapi->name eq "win16") {
$substitute->{replace} = "$ordinal $calling_convention16 $external_name(@argument_kinds) $internal_name";
} else {
$substitute->{replace} = "$ordinal $calling_convention32 $external_name(@argument_kinds) $internal_name";
}
if(!defined($spec_file{$module})) {
$spec_file{$module} = [];
}
if(!$abort) {
$spec_modified = 1;
push @{$spec_file{$module}}, $substitute;
}
}
}
}
my %found_external_names;
foreach my $external_name (@external_names) {
$found_external_names{$external_name} = {};
}
my $documentation_modified = 0;
if(!$spec_modified &&
($documentation && !$documentation_modified) &&
(options->documentation_name || options->documentation_ordinal ||
options->documentation_missing))
{ {
local $_; local $_;
my %found_external_names;
foreach my $external_name (@external_names) {
$found_external_names{$external_name} = 0;
}
my $line3; my $line3;
my $search; my $search;
my $replace; my $replace;
@ -257,7 +273,7 @@ foreach my $file (@c_files) {
my $line2 = $line - 1; my $line2 = $line - 1;
foreach (split(/\n/, $documentation)) { foreach (split(/\n/, $documentation)) {
$line2++; $line2++;
if(/^(\s*\*\s*(\w+|\@)\s*)((?:\s*[\(\[]\s*\w+(?:\s*\.\s*[^\s\)\]]*\s*)?[\)\]])+)(.*?)$/) { if(/^(\s*\*\s*(\S+)\s*)((?:\s*[\(\[]\s*\w+(?:\s*\.\s*[^\s\)\]]*\s*)?[\)\]])+)(.*?)$/) {
my $part1 = $1; my $part1 = $1;
my $external_name = $2; my $external_name = $2;
my $part3 = $3; my $part3 = $3;
@ -273,7 +289,10 @@ foreach my $file (@c_files) {
my $found = 0; my $found = 0;
foreach my $external_name2 (@external_names) { foreach my $external_name2 (@external_names) {
if($external_name eq $external_name2) { if($external_name eq $external_name2) {
$found_external_names{$external_name2} = 1; foreach my $entry (@entries) {
(undef, my $module, undef) = @$entry;
$found_external_names{$external_name2}{$module} = 1;
}
$found = 1; $found = 1;
last; last;
} }
@ -285,7 +304,7 @@ foreach my $file (@c_files) {
my $part12 = $part1; my $part12 = $part1;
(my $part32, my $module, my $ordinal) = @$entry; (my $part32, my $module, my $ordinal) = @$entry;
foreach my $entry2 (get_all_module_internal_ordinal($internal_name)) { foreach my $entry2 (winapi::get_all_module_internal_ordinal($internal_name)) {
(my $external_name2, my $module2, my $ordinal2) = @$entry2; (my $external_name2, my $module2, my $ordinal2) = @$entry2;
if(options->documentation_name && lc($module) eq $module2 && if(options->documentation_name && lc($module) eq $module2 &&
@ -324,19 +343,20 @@ foreach my $file (@c_files) {
$replace = $replace2; $replace = $replace2;
} }
$count++; $count++;
} elsif(/^(\s*\*\s*)(\w+|\@)\s*$/) { } elsif(/^(\s*\*\s*)([^\s\(]+)(?:\(\))?\s*$/) {
my $part1 = $1; my $part1 = $1;
my $external_name = $2; my $external_name = $2;
if($internal_name eq $external_name) {
foreach my $entry (get_all_module_internal_ordinal($internal_name)) { if($internal_name =~ /^(?:\S+_)?\Q$external_name\E(?:16)?$/) {
foreach my $entry (winapi::get_all_module_internal_ordinal($internal_name)) {
(my $external_name2, my $module, my $ordinal) = @$entry; (my $external_name2, my $module, my $ordinal) = @$entry;
$line3 = $line2; $line3 = $line2;
$search = "^\Q$_\E\$"; $search = "^\Q$_\E\$";
$replace = "$part1$external_name2 (\U$module\E.$ordinal)"; $replace = "$part1$external_name2 (\U$module\E.$ordinal)";
} }
$count++;
} }
$count++;
} }
} }
@ -344,22 +364,101 @@ foreach my $file (@c_files) {
if($count > 1 || $#external_names >= 1) { if($count > 1 || $#external_names >= 1) {
output->write("multiple entries (fixup not supported)\n"); output->write("multiple entries (fixup not supported)\n");
# output->write("s/$search/$replace/\n"); # output->write("s/$search/$replace/\n");
# output->write("@external_names\n");
} else { } else {
$documentation_modified = 1;
$substitute_line{$line3}{search} = $search; $substitute_line{$line3}{search} = $search;
$substitute_line{$line3}{replace} = $replace; $substitute_line{$line3}{replace} = $replace;
} }
} }
if(options->documentation_missing) {
foreach my $external_name (keys(%found_external_names)) {
if(!$found_external_names{$external_name}) {
output->write("$external_name missing (fixup not supported)\n");
}
}
}
} }
if(0 && !$documentation) { if(!$spec_modified && !$documentation_modified &&
options->documentation_missing && $documentation)
{
my $part1;
my $part2;
my $part3;
my $part4;
my $line3 = 0;
my $line2 = $line - 1;
foreach (split(/\n/, $documentation)) {
$line2++;
if(/^(\s*\*\s*)(\S+\s*)([\(\[])\s*\w+\s*\.\s*[^\s\)\]]*\s*([\)\]]).*?$/) {
$part1 = $1;
$part2 = $2;
$part3 = $3;
$part4 = $4;
$part2 =~ s/\S/ /g;
$line3 = $line2 + 1;
}
}
foreach my $entry2 (winapi::get_all_module_internal_ordinal($internal_name)) {
(my $external_name2, my $module2, my $ordinal2) = @$entry2;
my $found = 0;
foreach my $external_name (keys(%found_external_names)) {
foreach my $module3 (keys(%{$found_external_names{$external_name}})) {
if($external_name eq $external_name2 && uc($module2) eq $module3) {
$found = 1;
}
}
}
# FIXME: Not 100% correct
if(!$found &&
!$win16api->function_stub($internal_name) &&
!$win32api->function_stub($internal_name))
{
if($line3 > 0) {
$part2 = $external_name2 . " " x (length($part2) - length($external_name2));
$insert_line{$line3} = "$part1$part2$part3\U$module2\E.$ordinal2$part4\n";
} else {
output->write("$external_name2 (\U$module2\E.$ordinal2) missing (fixup not supported)\n");
}
}
}
}
if(!$documentation_modified &&
options->documentation_wrong)
{
my $line2 = $line - 1;
foreach (split(/\n/, $documentation)) {
$line2++;
if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
my $external_name = $1;
my $module = $2;
my $ordinal = $3;
my $found = 0;
foreach my $entry2 (winapi::get_all_module_internal_ordinal($internal_name)) {
(my $external_name2, my $module2, my $ordinal2) = @$entry2;
if($external_name eq $external_name2 &&
lc($module) eq $module2 &&
$ordinal eq $ordinal2)
{
$found = 1;
}
}
if(!$found) {
if(1) {
$delete_line{$line2} = "^\Q$_\E\$";
} else {
output->write("$external_name (\U$module\E.$ordinal) wrong (fixup not supported)\n");
};
}
}
}
}
if(0) # !$spec_modified && !$documentation
{
# FIXME: Not correct # FIXME: Not correct
my $external_name; my $external_name;
@ -380,64 +479,6 @@ foreach my $file (@c_files) {
} }
} }
if(options->stub) {
# FIXME: Not correct
foreach my $winapi (@winapis) {
if($winapi->function_stub($internal_name)) {
my $module = $winapi->function_internal_module($internal_name);
my $ordinal = $winapi->function_internal_ordinal($internal_name);
my $external_name = $internal_name;
if($winapi->name eq "win16") {
$external_name =~ s/(?:_)?16([AW]?)$//;
if(defined($1)) {
$external_name .= $1;
}
}
my $abort = 0;
my $n;
my @argument_kinds = map {
my $type = $_;
my $kind = "unknown";
$winapi->type_used_in_module($type, $module);
if(!defined($kind = $winapi->translate_argument($type))) {
output->write("no translation defined: " . $type . "\n");
}
# FIXME: Kludge
if(defined($kind) && $kind eq "longlong") {
$n += 2;
("long", "long");
} elsif(defined($kind)) {
$n++;
$kind;
} else {
$abort = 1;
$n++;
"undef";
}
} @argument_types;
my $substitute = {};
$substitute->{search} = "^\\s*$ordinal\\s+stub\\s+$external_name\\s*(?:#.*?)?\$";
if($winapi->name eq "win16") {
$substitute->{replace} = "$ordinal $calling_convention16 $external_name(@argument_kinds) $internal_name";
} else {
$substitute->{replace} = "$ordinal $calling_convention32 $external_name(@argument_kinds) $internal_name";
}
if(!defined($spec_file{$module})) {
$spec_file{$module} = [];
}
if(!$abort) {
push @{$spec_file{$module}}, $substitute;
}
}
}
}
$output->prefix(""); $output->prefix("");
}; };
@ -456,13 +497,24 @@ foreach my $file (@c_files) {
while(<IN>) { while(<IN>) {
chomp; chomp;
my $line = $insert_line{$.}; my $line;
$line = $insert_line{$.};
if(defined($line)) { if(defined($line)) {
if(options->modify) { if(options->modify) {
$_ = "$line$_"; $_ = "$line$_";
$modified = 1; $modified = 1;
} else { } else {
output->write("$file: $.: insert : '$line'\n"); my $line2 = $line; chomp($line2);
my @line2 = split(/\n/, $line2);
if($#line2 > 0) {
output->write("$file: $.: insert: \\\n");
foreach my $line2 (@line2) {
output->write("'$line2'\n");
}
} else {
output->write("$file: $.: insert: '$line2'\n");
}
} }
} }
@ -501,13 +553,31 @@ foreach my $file (@c_files) {
} }
} }
} }
$line = $delete_line{$.};
if(defined($line)) {
if(/$line/) {
if(options->modify) {
$modified = 1;
next;
} else {
output->write("$file: $.: delete: '$line'\n");
}
} else {
output->write("$file: $.: unmatched delete: '$line'\n");
}
}
print OUT "$_\n"; print OUT "$_\n";
} }
return $modified; return $modified;
}; };
my $n = 0; while(defined(each %substitute_line)) { $n++; } my $n = 0;
while(defined(each %insert_line)) { $n++; }
while(defined(each %substitute_line)) { $n++; }
while(defined(each %delete_line)) { $n++; }
if($n > 0) { if($n > 0) {
edit_file($file, $editor); edit_file($file, $editor);
} }

View File

@ -98,6 +98,8 @@ dlls/imm32
% dlls/kernel/kernel.spec % dlls/kernel/kernel.spec
dlls/kernel dlls/kernel
dlls/shell32
dlls/win32s
files files
loader/ne loader/ne
loader loader
@ -130,6 +132,7 @@ dlls/kernel
% dlls/kernel/system.spec % dlls/kernel/system.spec
memory
misc misc
% dlls/kernel/toolhelp.spec % dlls/kernel/toolhelp.spec
@ -138,7 +141,6 @@ dlls/kernel
loader/ne loader/ne
loader loader
memory memory
windows
% dlls/kernel/wprocs.spec % dlls/kernel/wprocs.spec
@ -185,6 +187,7 @@ dlls/msvideo
% dlls/ntdll/ntdll.spec % dlls/ntdll/ntdll.spec
dlls/ntdll dlls/ntdll
memory
misc misc
scheduler scheduler
@ -262,6 +265,10 @@ dlls/opengl32
dlls/psapi dlls/psapi
% dlls/quartz/quartz.spec
dlls/quartz
% dlls/rasapi32/rasapi16.spec % dlls/rasapi32/rasapi16.spec
% dlls/rasapi32/rasapi32.spec % dlls/rasapi32/rasapi32.spec
@ -291,10 +298,12 @@ dlls/setupapi
% dlls/shell32/shell.spec % dlls/shell32/shell.spec
dlls/shell32 dlls/shell32
misc
% dlls/shell32/shell32.spec % dlls/shell32/shell32.spec
dlls/shell32 dlls/shell32
memory
% dlls/shdocvw/shdocvw.spec % dlls/shdocvw/shdocvw.spec
@ -342,6 +351,7 @@ controls
dlls/kernel dlls/kernel
dlls/user dlls/user
memory memory
misc
windows windows
% dlls/user/user32.spec % dlls/user/user32.spec
@ -350,6 +360,7 @@ controls
dlls/user dlls/user
dlls/user/dde dlls/user/dde
loader loader
objects
windows windows
% dlls/version/ver.spec % dlls/version/ver.spec
@ -366,14 +377,12 @@ dlls/win32s
% dlls/win32s/w32sys.spec % dlls/win32s/w32sys.spec
dlls/kernel
dlls/win32s dlls/win32s
% dlls/win32s/win32s16.spec % dlls/win32s/win32s16.spec
dlls/kernel
dlls/win32s dlls/win32s
memory
scheduler
% dlls/winaspi/winaspi.spec % dlls/winaspi/winaspi.spec

View File

@ -12,9 +12,9 @@ UINT
int int
%ptr %ptr
BITMAP16 * BITMAP16 *
BITMAPINFO * BITMAPINFO *
BITMAPINFOHEADER *
DEVMODEA * DEVMODEA *
DOCINFO16 * DOCINFO16 *
FARPROC16 * FARPROC16 *

View File

@ -24,6 +24,7 @@ LPOLEUIEDITLINKSW
LPOLEUIINSERTOBJECTA LPOLEUIINSERTOBJECTA
LPOLEUIINSERTOBJECTW LPOLEUIINSERTOBJECTW
LPOLEUILINKCONTAINERA LPOLEUILINKCONTAINERA
LPOLEUILINKCONTAINERW
LPOLEUIOBJECTPROPSA LPOLEUIOBJECTPROPSA
LPOLEUIOBJECTPROPSW LPOLEUIOBJECTPROPSW
LPOLEUIPASTESPECIALA LPOLEUIPASTESPECIALA
@ -38,3 +39,4 @@ LPSTR
%wstr %wstr
LPCWSTR LPCWSTR
LPWSTR

View File

@ -0,0 +1,10 @@
%long
DWORD
HRESULT
%ptr
CLSID *
IID *
void **

View File

@ -79,7 +79,7 @@ UINT *
WORD * WORD *
YIELDPROC YIELDPROC
%ptr --forbidden %ptr # --forbidden
LPMMIOPROC16 LPMMIOPROC16

View File

@ -3,10 +3,7 @@
DWORD DWORD
INT INT
SOCKET SOCKET
UINT
%long # --forbidden
long
%ptr %ptr

View File

@ -2,6 +2,8 @@ package winapi;
use strict; use strict;
my @winapis;
sub new { sub new {
my $proto = shift; my $proto = shift;
my $class = ref($proto) || $proto; my $class = ref($proto) || $proto;
@ -28,6 +30,8 @@ sub new {
$self->parse_api_file($file,$module); $self->parse_api_file($file,$module);
} }
push @winapis, $self;
return $self; return $self;
} }
@ -285,7 +289,6 @@ sub parse_spec_file {
$ordinal = $1; $ordinal = $1;
# FIXME: Internal name existing more than once not handled properly
if(!$$function_internal_name{$external_name}) { if(!$$function_internal_name{$external_name}) {
$$function_internal_name{$external_name} = $internal_name; $$function_internal_name{$external_name} = $internal_name;
} else { } else {
@ -358,7 +361,7 @@ sub parse_spec_file {
$ordinal = $1; $ordinal = $1;
my $internal_name; my $internal_name;
if($type eq "win16") { if(0 && $type eq "win16") {
if($external_name =~ /\d$/) { if($external_name =~ /\d$/) {
$internal_name = $external_name . "_16"; $internal_name = $external_name . "_16";
} else { } else {
@ -368,8 +371,17 @@ sub parse_spec_file {
$internal_name = $external_name; $internal_name = $external_name;
} }
# FIXME: Internal name existing more than once not handled properly $$function_stub{$external_name} = 1;
$$function_stub{$internal_name} = 1; if(!$$function_internal_name{$external_name}) {
$$function_internal_name{$external_name} = $internal_name;
} else {
$$function_internal_name{$external_name} .= " & $internal_name";
}
if(!$$function_external_name{$internal_name}) {
$$function_external_name{$internal_name} = $external_name;
} else {
$$function_external_name{$internal_name} .= " & $external_name";
}
if(!$$function_internal_ordinal{$internal_name}) { if(!$$function_internal_ordinal{$internal_name}) {
$$function_internal_ordinal{$internal_name} = $ordinal; $$function_internal_ordinal{$internal_name} = $ordinal;
} else { } else {
@ -802,4 +814,84 @@ sub internal_function_found {
return $$function_found{$name}; return $$function_found{$name};
} }
########################################################################
# class methods
#
sub get_all_module_internal_ordinal {
my $internal_name = shift;
my @entries = ();
foreach my $winapi (@winapis) {
my @name = (); {
my $name = $winapi->function_external_name($internal_name);
if(defined($name)) {
@name = split(/ & /, $name);
}
}
my @module = (); {
my $module = $winapi->function_internal_module($internal_name);
if(defined($module)) {
@module = split(/ & /, $module);
}
}
my @ordinal = (); {
my $ordinal = $winapi->function_internal_ordinal($internal_name);
if(defined($ordinal)) {
@ordinal = split(/ & /, $ordinal);
}
}
my $name;
my $module;
my $ordinal;
while(defined($name = shift @name) &&
defined($module = shift @module) &&
defined($ordinal = shift @ordinal))
{
push @entries, [$name, $module, $ordinal];
}
}
return @entries;
}
sub get_all_module_external_ordinal {
my $external_name = shift;
my @entries = ();
foreach my $winapi (@winapis) {
my @name = (); {
my $name = $winapi->function_internal_name($external_name);
if(defined($name)) {
@name = split(/ & /, $name);
}
}
my @module = (); {
my $module = $winapi->function_external_module($external_name);
if(defined($module)) {
@module = split(/ & /, $module);
}
}
my @ordinal = (); {
my $ordinal = $winapi->function_external_ordinal($external_name);
if(defined($ordinal)) {
@ordinal = split(/ & /, $ordinal);
}
}
my $name;
my $module;
my $ordinal;
while(defined($name = shift @name) &&
defined($module = shift @module) &&
defined($ordinal = shift @ordinal))
{
push @entries, [$name, $module, $ordinal];
}
}
return @entries;
}
1; 1;

View File

@ -352,6 +352,8 @@ foreach my $file (@c_files) {
my @argument_documentations = @$refargument_documentations; my @argument_documentations = @$refargument_documentations;
my $statements = shift; my $statements = shift;
my $documentation_line = $line;
my $external_name16 = $win16api->function_external_name($internal_name); my $external_name16 = $win16api->function_external_name($internal_name);
my $external_name32 = $win32api->function_external_name($internal_name); my $external_name32 = $win32api->function_external_name($internal_name);
@ -372,10 +374,14 @@ foreach my $file (@c_files) {
my $module32 = $win32api->function_internal_module($internal_name); my $module32 = $win32api->function_internal_module($internal_name);
if(defined($module16)) { if(defined($module16)) {
$modules->found_module_in_dir($module16, $file_dir); foreach my $module (split(/ & /, $module16)) {
$modules->found_module_in_dir($module, $file_dir);
}
} }
if(defined($module32)) { if(defined($module32)) {
$modules->found_module_in_dir($module32, $file_dir); foreach my $module (split(/ & /, $module32)) {
$modules->found_module_in_dir($module, $file_dir);
}
} }
my $previous_function; my $previous_function;
@ -387,6 +393,7 @@ foreach my $file (@c_files) {
$functions{$internal_name} = $function; $functions{$internal_name} = $function;
$function->documentation($documentation); $function->documentation($documentation);
$function->documentation_line($documentation_line);
$function->linkage($linkage); $function->linkage($linkage);
$function->file($file); $function->file($file);
$function->return_type($return_type); $function->return_type($return_type);
@ -428,33 +435,46 @@ foreach my $file (@c_files) {
} }
if($options->local && $options->misplaced && if($options->local && $options->misplaced &&
$linkage ne "extern" && $statements) $linkage ne "extern" && defined($statements))
{ {
if($options->win16 && $options->report_module($module16)) { if($options->win16 && $options->report_module($module16)) {
my $match = 0;
foreach my $module (split(/ & /, $module16)) { foreach my $module (split(/ & /, $module16)) {
my $match = 0;
foreach my $file_module (split(/ & /, $file_module16)) { foreach my $file_module (split(/ & /, $file_module16)) {
if($module eq $file_module) { if($module eq $file_module) {
$match++; $match = 1;
} }
} }
} if(!$match) {
if(!$match && $file ne "library/port.c" && !$nativeapi->is_function($internal_name)) { if($file ne "library/port.c" &&
$output->write("is misplaced\n"); !$nativeapi->is_function($internal_name) &&
!$win16api->function_stub($internal_name))
{
$output->write("is misplaced ($module)\n");
}
last;
}
} }
} }
if($options->win32 && $options->report_module($module32)) { if($options->win32 && $options->report_module($module32)) {
my $match = 0;
foreach my $module (split(/ & /, $module32)) { foreach my $module (split(/ & /, $module32)) {
my $match = 0;
foreach my $file_module (split(/ & /, $file_module32)) { foreach my $file_module (split(/ & /, $file_module32)) {
if($module eq $file_module) { if($module eq $file_module) {
$match++; $match = 1;
} }
} }
} if(!$match) {
if(!$match && $file ne "library/port.c" && !$nativeapi->is_function($internal_name)) { if($file ne "library/port.c" &&
$output->write("is misplaced\n"); !$nativeapi->is_function($internal_name) &&
!$win32api->function_stub($internal_name))
{
$output->write("is misplaced ($module)\n");
}
last;
}
} }
} }
} }
@ -527,7 +547,7 @@ foreach my $file (@c_files) {
if($options->local && $options->documentation && if($options->local && $options->documentation &&
!defined($previous_function) && !defined($previous_function) &&
(defined($module16) || defined($module32)) && (defined($module16) || defined($module32)) &&
$linkage ne "extern" && $statements) $linkage ne "extern" && defined($statements))
{ {
winapi_documentation::check_documentation $options, $output, $win16api, $win32api, $function; winapi_documentation::check_documentation $options, $output, $win16api, $win32api, $function;
} }

View File

@ -7,6 +7,8 @@ my %comment_indent;
my %comment_spacing; my %comment_spacing;
sub check_documentation { sub check_documentation {
local $_;
my $options = shift; my $options = shift;
my $output = shift; my $output = shift;
my $win16api = shift; my $win16api = shift;
@ -19,126 +21,92 @@ sub check_documentation {
my $external_name32 = $function->external_name32; my $external_name32 = $function->external_name32;
my $internal_name = $function->internal_name; my $internal_name = $function->internal_name;
my $documentation = $function->documentation; my $documentation = $function->documentation;
my $documentation_line = $function->documentation_line;
my @argument_documentations = @{$function->argument_documentations}; my @argument_documentations = @{$function->argument_documentations};
# FIXME: Not correct if($options->documentation_name ||
if(defined($external_name16)) { $options->documentation_ordinal ||
$external_name16 = (split(/\s*&\s*/, $external_name16))[0]; $options->documentation_pedantic)
} {
my @winapis = ($win16api, $win32api);
# FIXME: Not correct my @modules = ($module16, $module32);
if(defined($external_name32)) { my @external_names = ($external_name16, $external_name32);
$external_name32 = (split(/\s*&\s*/, $external_name32))[0]; while(
} defined(my $winapi = shift @winapis) &&
defined(my $external_name = shift @external_names) &&
my $external_name; defined(my $module = shift @modules))
my $name1;
my $name2;
if(defined($module16) && !defined($module32)) {
my @uc_modules16 = split(/\s*\&\s*/, uc($module16));
push @uc_modules16, "WIN16";
$name1 = $internal_name;
foreach my $uc_module16 (@uc_modules16) {
if($name1 =~ s/^$uc_module16\_//) { last; }
}
$name2 = $name1;
$name2 =~ s/(?:_)?16$//;
$name2 =~ s/16_fn/16_/;
$external_name = $external_name16;
} elsif(!defined($module16) && defined($module32)) {
my @uc_modules32 = split(/\s*\&\s*/, uc($module32));
push @uc_modules32, "wine";
foreach my $uc_module32 (@uc_modules32) {
if($uc_module32 =~ /^WS2_32$/) {
push @uc_modules32, "WSOCK32";
}
}
$name1 = $internal_name;
foreach my $uc_module32 (@uc_modules32) {
if($name1 =~ s/^$uc_module32\_//) { last; }
}
$name2 = $name1;
$name2 =~ s/AW$//;
$external_name = $external_name32;
} else {
my @uc_modules = split(/\s*\&\s*/, uc($module16));
push @uc_modules, split(/\s*\&\s*/, uc($module32));
$name1 = $internal_name;
foreach my $uc_module (@uc_modules) {
if($name1 =~ s/^$uc_module\_//) { last; }
}
$name2 = $name1;
$external_name = $external_name32;
}
if(!defined($external_name)) {
$external_name = $internal_name;
}
if($options->documentation_name) {
my $n = 0;
if((++$n && defined($module16) && defined($external_name16) &&
$external_name16 ne "@" && $documentation !~ /\b\Q$external_name16\E\b/) ||
(++$n && defined($module16) && defined($external_name16) &&
$external_name16 eq "@" && $documentation !~ /\@/) ||
(++$n && defined($module32) && defined($external_name32) &&
$external_name32 ne "@" && $documentation !~ /\b\Q$external_name32\E\b/) ||
(++$n && defined($module32) && defined($external_name32) &&
$external_name32 eq "@" && $documentation !~ /\@/))
{ {
my $external_name = ($external_name16, $external_name32)[($n-1)/2]; if($winapi->function_stub($internal_name)) { next; }
if($options->documentation_pedantic || $documentation !~ /\b(?:$internal_name|$name1|$name2)\b/) {
$output->write("documentation: wrong or missing name ($external_name) \\\n$documentation\n"); my @external_name = split(/\s*\&\s*/, $external_name);
my @modules = split(/\s*\&\s*/, $module);
my @ordinals = split(/\s*\&\s*/, $winapi->function_internal_ordinal($internal_name));
my $pedantic_failed = 0;
while(defined(my $external_name = shift @external_name) &&
defined(my $module = shift @modules) &&
defined(my $ordinal = shift @ordinals))
{
my $found_name = 0;
my $found_ordinal = 0;
foreach (split(/\n/, $documentation)) {
if(/^(\s*)\*(\s*)(\@|\S+)(\s*)([\(\[])(\w+)\.(\@|\d+)([\)\]])/) {
my $external_name2 = $3;
my $module2 = $6;
my $ordinal2 = $7;
if(length($1) != 1 || length($2) < 1 ||
length($4) < 1 || $5 ne "(" || $8 ne ")")
{
$pedantic_failed = 1;
}
if($external_name eq $external_name2) {
$found_name = 1;
if("\U$module\E" eq $module2 &&
$ordinal eq $ordinal2)
{
$found_ordinal = 1;
}
}
}
}
if(($options->documentation_name && !$found_name) ||
($options->documentation_ordinal && !$found_ordinal))
{
$output->write("documentation: expected $external_name (\U$module\E.$ordinal): \\\n$documentation\n");
}
}
if($options->documentation_pedantic && $pedantic_failed) {
$output->write("documentation: pedantic failed: \\\n$documentation\n");
} }
} }
} }
if($options->documentation_ordinal) { if($options->documentation_wrong) {
if(defined($module16)) { foreach (split(/\n/, $documentation)) {
my @modules16 = split(/\s*\&\s*/, $module16); if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
my @ordinals16 = split(/\s*\&\s*/, $win16api->function_internal_ordinal($internal_name)); my $external_name = $1;
my $module = $2;
my $ordinal = $3;
my $module16; my $found = 0;
my $ordinal16; foreach my $entry2 (winapi::get_all_module_internal_ordinal($internal_name)) {
while(defined($module16 = shift @modules16) && defined($ordinal16 = shift @ordinals16)) { (my $external_name2, my $module2, my $ordinal2) = @$entry2;
if($documentation !~ /\b\U$module16\E\.\Q$ordinal16\E/) {
$output->write("documentation: wrong or missing ordinal " . if($external_name eq $external_name2 &&
"expected (\U$module16\E.$ordinal16) \\\n$documentation\n"); lc($module) eq $module2 &&
$ordinal eq $ordinal2)
{
$found = 1;
}
}
if(!$found) {
$output->write("documentation: $external_name (\U$module\E.$ordinal) wrong\n");
} }
} }
} }
if(defined($module32)) {
my @modules32 = split(/\s*\&\s*/, $module32);
my @ordinals32 = split(/\s*\&\s*/, $win32api->function_internal_ordinal($internal_name));
my $module32;
my $ordinal32;
while(defined($module32 = shift @modules32) && defined($ordinal32 = shift @ordinals32)) {
if($documentation !~ /\b\U$module32\E\.\Q$ordinal32\E/) {
$output->write("documentation: wrong or missing ordinal " .
"expected (\U$module32\E.$ordinal32) \\\n$documentation\n");
}
}
}
}
# FIXME: Not correct
if($options->documentation_pedantic) {
my $ordinal = (split(/\s*\&\s*/, $win16api->function_internal_ordinal($internal_name)))[0];
if(defined($ordinal) && $documentation !~ /^ \*\s+(?:\@|\w+)(?:\s+[\(\[]\w+\.(?:\@|\d+)[\)\]])+/m) {
$output->write("documentation: pedantic check failed \\\n$documentation\n");
}
} }
if($options->documentation_comment_indent) { if($options->documentation_comment_indent) {

View File

@ -33,6 +33,17 @@ sub documentation {
return $$documentation; return $$documentation;
} }
sub documentation_line {
my $self = shift;
my $documentation_line = \${$self->{DOCUMENTATION_LINE}};
local $_ = shift;
if(defined($_)) { $$documentation_line = $_; }
return $$documentation_line;
}
sub linkage { sub linkage {
my $self = shift; my $self = shift;
my $linkage = \${$self->{LINKAGE}}; my $linkage = \${$self->{LINKAGE}};

View File

@ -122,7 +122,7 @@ sub check_function {
$output->write("function not implemented as vararg\n"); $output->write("function not implemented as vararg\n");
} }
} elsif($#argument_types != -1 && $argument_types[$#argument_types] eq "...") { } elsif($#argument_types != -1 && $argument_types[$#argument_types] eq "...") {
if($#argument_types == 0) { if($#argument_types == 0 || $winapi->name eq "win16") {
pop @argument_types; pop @argument_types;
} else { } else {
$output->write("function not declared as vararg\n"); $output->write("function not declared as vararg\n");

View File

@ -102,10 +102,15 @@ my %options = (
description => "check for documentation name inconsistances\n" description => "check for documentation name inconsistances\n"
}, },
"documentation-ordinal" => { "documentation-ordinal" => {
default => 0, default => 1,
parent => "documentation", parent => "documentation",
description => "check for documentation ordinal inconsistances\n" description => "check for documentation ordinal inconsistances\n"
}, },
"documentation-wrong" => {
default => 1,
parent => "documentation",
description => "check for wrong documentation\n"
},
"prototype" => {default => 0, parent => ["local", "headers"], description => "prototype checking" }, "prototype" => {default => 0, parent => ["local", "headers"], description => "prototype checking" },
"global" => { default => 1, description => "global checking" }, "global" => { default => 1, description => "global checking" },