- Updated API files
- Better headers and prototype checking
- Prototype checking now called --prototype instead of --headers
- New options --headers-{duplicated,misplaced} for
duplicated/misplaced functions checking of the headers.
- Minor bug fixes.
diff --git a/tools/winapi_check/modules.dat b/tools/winapi_check/modules.dat
index e40f151..e1d3892 100644
--- a/tools/winapi_check/modules.dat
+++ b/tools/winapi_check/modules.dat
@@ -145,14 +145,21 @@
dlls/ole32
-% dlls/ole32/ole2nls.spec
-
-dlls/ole32
-
% dlls/ole32/ole32.spec
dlls/ole32
+% dlls/ole32/ole2conv.spec
+
+% dlls/ole32/ole2nls.spec
+
+dlls/ole32
+ole
+
+% dlls/ole32/ole2prox.spec
+
+% dlls/ole32/ole2thk.spec
+
% dlls/ole32/storage.spec
dlls/ole32
@@ -258,6 +265,11 @@
memory
windows
+% dlls/user/ddeml.spec
+
+dlls/user
+misc
+
% dlls/user/user.spec
controls
@@ -393,10 +405,6 @@
% if1632/comm.spec
-% if1632/ddeml.spec
-
-misc
-
% if1632/dispdib.spec
graphics
@@ -414,16 +422,6 @@
scheduler
win32
-% if1632/ole2conv.spec
-
-% if1632/ole2nls.spec
-
-ole
-
-% if1632/ole2prox.spec
-
-% if1632/ole2thk.spec
-
% if1632/system.spec
misc
diff --git a/tools/winapi_check/modules.pm b/tools/winapi_check/modules.pm
index 2018533..e1d2cb4 100644
--- a/tools/winapi_check/modules.pm
+++ b/tools/winapi_check/modules.pm
@@ -52,6 +52,11 @@
if(/^%\s+(.*?)$/) {
$spec_file = $1;
+
+ if(!-f "$wine_dir/$spec_file") {
+ $$output->write("$module_file: $spec_file: file ($spec_file) doesn't exist or is no file\n");
+ }
+
if($wine_dir eq ".") {
$all_spec_files{$spec_file}--;
} else {
diff --git a/tools/winapi_check/nativeapi.dat b/tools/winapi_check/nativeapi.dat
index 8a3de0f..6e0c0af 100644
--- a/tools/winapi_check/nativeapi.dat
+++ b/tools/winapi_check/nativeapi.dat
@@ -16,6 +16,7 @@
_xmknod
_xstat
abs
+accept
access
acos
asctime
@@ -26,14 +27,18 @@
atof
atoi
atol
+bind
bsearch
bzero
calloc
ceil
cfgetospeed
chmod
+clock
close
closedir
+closesocket
+connect
cos
cosh
ctime
@@ -66,23 +71,39 @@
fread
free
frexp
+freopen
+fscanf
fseek
fsetpos
fsync
+ftell
ftruncate
fwrite
+getc
getcwd
getenv
+gethostbyaddr
+gethostbyname
+gethostname
getlogin
getnetbyname
+getpeername
getpid
getpwuid
+gets
+getservbyname
+getsockname
gettimeofday
getuid
gmtime
+htonl
+htons
hypot
+inet_addr
inet_network
+inet_ntoa
ioctl
+ioctlsocket
isalnum
isalpha
isatty
@@ -102,6 +123,7 @@
labs
ldexp
ldiv
+listen
localtime
log
log10
@@ -121,6 +143,8 @@
mprotect
msync
munmap
+ntohl
+ntohs
open
opendir
perror
@@ -128,6 +152,7 @@
poll
pow
printf
+putc
putchar
putenv
puts
@@ -137,19 +162,25 @@
read
readdir
realloc
+recv
+recvfrom
remove
rename
rmdir
select
+send
+sendto
setbuf
setlocale
setsid
+setsockopt
settimeofday
setvbuf
shmat
shmctl
shmdt
shmget
+shutdown
sigaction
sigaddset
sigaltstack
@@ -160,6 +191,7 @@
sin
sinh
sleep
+socket
snprintf
sprintf
sqrt
diff --git a/tools/winapi_check/win32/opengl32.api b/tools/winapi_check/win32/opengl32.api
index 7e874ee..fd8d7d8 100644
--- a/tools/winapi_check/win32/opengl32.api
+++ b/tools/winapi_check/win32/opengl32.api
@@ -1,3 +1,8 @@
+%double
+
+GLclampd
+GLdouble
+
%long
BOOL
@@ -6,9 +11,7 @@
GLbitfield
GLboolean
GLbyte
-GLclampd
GLclampf
-GLdouble
GLenum
GLfloat
GLint
diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm
index c91cdab..cc96b70 100644
--- a/tools/winapi_check/winapi.pm
+++ b/tools/winapi_check/winapi.pm
@@ -215,6 +215,7 @@
my $output = \${$self->{OUTPUT}};
my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}};
my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
+ my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
my $function_stub = \%{$self->{FUNCTION_STUB}};
my $function_module = \%{$self->{FUNCTION_MODULE}};
my $modules = \%{$self->{MODULES}};
@@ -256,6 +257,7 @@
$ordinal = $1;
# FIXME: Internal name existing more than once not handled properly
+ $$function_external_name{$internal_name} = $external_name;
$$function_arguments{$internal_name} = $arguments;
$$function_calling_convention{$internal_name} = $calling_convention;
if(!$$function_module{$internal_name}) {
@@ -571,6 +573,15 @@
return $$function_calling_convention{$name};
}
+sub function_external_name {
+ my $self = shift;
+ my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
+
+ my $name = shift;
+
+ return $$function_external_name{$name};
+}
+
sub is_function {
my $self = shift;
my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check
index 75e6aa2..f517dfa 100755
--- a/tools/winapi_check/winapi_check
+++ b/tools/winapi_check/winapi_check
@@ -1,6 +1,16 @@
#!/usr/bin/perl -w
-# Copyright 1999 Patrik Stridvall
+# Copyright 1999-2000 Patrik Stridvall
+
+# Note that winapi_check are using heuristics quite heavily.
+# So always remember that:
+#
+# "Heuristics are bug ridden by definition.
+# If they didn't have bugs, then they'd be algorithms."
+#
+# In other words, reported bugs are only potential bugs not
+# real bugs, so they are called issues rather than bugs.
+#
use strict;
@@ -92,6 +102,7 @@
my $win16api = 'winapi'->new($options, $output, "win16", "$winapi_check_dir/win16");
my $win32api = 'winapi'->new($options, $output, "win32", "$winapi_check_dir/win32");
+my @winapis = ($win16api, $win32api);
if($options->global) {
'winapi'->read_all_spec_files($modules, $wine_dir, $current_dir, \&file_type, $win16api, $win32api);
@@ -176,12 +187,49 @@
my $linkage = shift;
my $return_type = shift;
my $calling_convention = shift;
- my $name = shift;
- my $refarguments = shift;
- my @arguments = @$refarguments;
+ my $internal_name = shift;
+ my $refargument_types = shift;
+ my @argument_types = @$refargument_types;
+ my $refargument_names = shift;
+ my @argument_names = @$refargument_names;
my $statements = shift;
-
- $declared_functions{$name}++;
+
+ foreach my $winapi (@winapis) {
+ my $module = $winapi->function_module($internal_name);
+ if(!defined($module)) { next }
+
+ my $external_name = $winapi->function_external_name($internal_name);
+ # FIXME: Kludge because of the THUNK variants
+ if(!defined($external_name)) {
+ next;
+ }
+
+ my $output_function = sub {
+ my $message = shift;
+
+ $output->write("$file: $module: $return_type ");
+ $output->write("$calling_convention ") if $calling_convention;
+ $output->write("$internal_name(" . join(",", @argument_types) . "): $message\n");
+ };
+
+ if(!defined($declared_functions{$winapi->name}{$external_name})) {
+ $declared_functions{$winapi->name}{$external_name} = "$file";
+ } elsif($options->headers_duplicated) {
+ my $message = "declared more than once";
+ if($file ne $declared_functions{$winapi->name}{$external_name}) {
+ $message .= ", first declaration in '" . $declared_functions{$winapi->name}{$external_name} . "'";
+ }
+ &$output_function("$message");
+ }
+
+ if($options->headers_misplaced) {
+ if($file =~ /^include\/[^\/]*$/ && $winapi->name eq "win16") {
+ &$output_function("declaration misplaced");
+ } elsif($file =~ /^include\/wine\/[^\/]*$/ && $winapi->name eq "win32") {
+ &$output_function("declaration misplaced");
+ }
+ }
+ }
};
my $found_preprocessor = sub {
@@ -221,13 +269,15 @@
my $return_type = shift;
my $calling_convention = shift;
my $internal_name = shift;
- my $external_name = $internal_name;
my $refargument_types = shift;
my @argument_types = @$refargument_types;
my $refargument_names = shift;
my @argument_names = @$refargument_names;
my $statements = shift;
+ my $external_name16 = $win16api->function_external_name($internal_name);
+ my $external_name32 = $win32api->function_external_name($internal_name);
+
if($options->global) {
$win16api->found_type($return_type) if $options->win16;
$win32api->found_type($return_type) if $options->win32;
@@ -242,40 +292,7 @@
if($file_type ne "application") {
my $module16 = $win16api->function_module($internal_name);
- if(!defined($module16)) {
- if($internal_name =~ /^(.*?)_(.*?)$/) {
- my $module2 = lc($1);
- my $name2 = $2;
- if($win16api->is_module($module2)) {
- $module16 = $win16api->function_module($name2);
- if(defined($module16)) {
- if(uc($module16) !~ /\U$module2\E/) {
- $external_name = $name2;
- } else {
- $module16 = undef;
- }
- }
- }
- }
- }
-
my $module32 = $win32api->function_module($internal_name);
- if(!defined($module32)) {
- if($internal_name =~ /^(.*?)_(.*?)$/) {
- my $module2 = lc($1);
- my $name2 = $2;
- if($win32api->is_module($module2)) {
- $module32 = $win32api->function_module($name2);
- if(defined($module32)) {
- if(uc($module32) =~ /\U$module2\E/) {
- $external_name = $name2;
- } else {
- $module32 = undef;
- }
- }
- }
- }
- }
my $function = 'winapi_function'->new;
$functions{$internal_name} = $function;
@@ -285,7 +302,8 @@
$function->file($file);
$function->return_type($return_type);
$function->calling_convention($calling_convention);
- $function->external_name($external_name);
+ $function->external_name16($external_name16);
+ $function->external_name32($external_name32);
$function->internal_name($internal_name);
$function->argument_types([@argument_types]);
$function->argument_names([@argument_names]);
@@ -337,25 +355,43 @@
}
}
- if($options->local && $options->headers) {
- if(!$declared_functions{$internal_name}) {
- if($options->win16 && $options->report_module($module16)) {
- &$output16("no prototype");
+ if($options->local && $options->headers && $options->prototype) {
+ if($options->win16 && $options->report_module($module16)) {
+ if(!defined($external_name16) || (!$nativeapi->is_function($external_name16) &&
+ !defined($declared_functions{$win16api->name}{$external_name16})))
+ {
+ if(!defined($external_name16) || ($external_name16 !~ /^DllEntryPoint$/ &&
+ $internal_name !~ /^I(?:Malloc|Storage)16_fn/ &&
+ $internal_name !~ /^(?:\Q$module16\E|THUNK|WIN16)_\Q$external_name16\E(?:16)?$/))
+ {
+ &$output16("no prototype");
+ }
}
- if($options->win32 && $options->report_module($module32)) {
- &$output32("no prototype");
+ }
+
+ if($options->win32 && $options->report_module($module32)) {
+ if(!defined($external_name32) || (!$nativeapi->is_function($external_name32) && !defined($declared_functions{$win32api->name}{$external_name32})))
+ {
+ if(!defined($external_name32) || ($external_name32 !~ /^Dll(?:
+ Install|CanUnloadNow|GetClassObject|GetVersion|
+ RegisterServer|RegisterServerEx|UnregisterServer)|DriverProc$/x &&
+ $internal_name !~ /^COMCTL32_Str/ &&
+ $internal_name !~ /^(?:\Q$module32\E|wine)_(?:\Q$external_name32\E|\d+)$/))
+ {
+ &$output32("no prototype");
+ }
}
- }
+ }
}
if($options->local && $options->argument) {
if($options->win16 && $options->report_module($module16)) {
winapi_local::check_function $options, $output16,
- $return_type, $calling_convention, $external_name, $internal_name, [@argument_types], $win16api;
+ $return_type, $calling_convention, $external_name16, $internal_name, [@argument_types], $win16api;
}
if($options->win32 && $options->report_module($module32)) {
winapi_local::check_function $options, $output32,
- $return_type, $calling_convention, $external_name, $internal_name, [@argument_types], $win32api;
+ $return_type, $calling_convention, $external_name32, $internal_name, [@argument_types], $win32api;
}
}
diff --git a/tools/winapi_check/winapi_function.pm b/tools/winapi_check/winapi_function.pm
index fa166ca..50a52b5 100644
--- a/tools/winapi_check/winapi_function.pm
+++ b/tools/winapi_check/winapi_function.pm
@@ -66,15 +66,26 @@
return $$calling_convention;
}
-sub external_name {
+sub external_name16 {
my $self = shift;
- my $external_name = \${$self->{EXTERNAL_NAME}};
+ my $external_name16 = \${$self->{EXTERNAL_NAME16}};
local $_ = shift;
- if(defined($_)) { $$external_name = $_; }
+ if(defined($_)) { $$external_name16 = $_; }
- return $$external_name;
+ return $$external_name16;
+}
+
+sub external_name32 {
+ my $self = shift;
+ my $external_name32 = \${$self->{EXTERNAL_NAME32}};
+
+ local $_ = shift;
+
+ if(defined($_)) { $$external_name32 = $_; }
+
+ return $$external_name32;
}
sub internal_name {
diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm
index 576c572..5dd90a4 100644
--- a/tools/winapi_check/winapi_local.pm
+++ b/tools/winapi_check/winapi_local.pm
@@ -13,23 +13,23 @@
my @argument_types = @$refargument_types;
my $winapi = shift;
- my $module = $winapi->function_module($external_name);
+ my $module = $winapi->function_module($internal_name);
if($winapi->name eq "win16") {
- my $name16 = $external_name;
+ my $name16 = $internal_name;
$name16 =~ s/16$//;
- if($name16 ne $external_name && $winapi->function_stub($name16)) {
+ if($name16 ne $internal_name && $winapi->function_stub($name16)) {
if($options->implemented) {
&$output("function implemented but declared as stub in .spec file");
}
return;
- } elsif($winapi->function_stub($external_name)) {
+ } elsif($winapi->function_stub($internal_name)) {
if($options->implemented_win32) {
&$output("32-bit variant of function implemented but declared as stub in .spec file");
}
return;
}
- } elsif($winapi->function_stub($external_name)) {
+ } elsif($winapi->function_stub($internal_name)) {
if($options->implemented) {
&$output("function implemented but declared as stub in .spec file");
}
@@ -80,8 +80,8 @@
}
}
- my $declared_calling_convention = $winapi->function_calling_convention($external_name);
- my @declared_argument_kinds = split(/\s+/, $winapi->function_arguments($external_name));
+ my $declared_calling_convention = $winapi->function_calling_convention($internal_name);
+ my @declared_argument_kinds = split(/\s+/, $winapi->function_arguments($internal_name));
if($declared_calling_convention =~ /^register|interrupt$/) {
push @declared_argument_kinds, "ptr";
@@ -112,7 +112,7 @@
}
if($#argument_types != -1 && $argument_types[$#argument_types] eq "CONTEXT *" &&
- $external_name !~ /^(Get|Set)ThreadContext$/) # FIXME: Kludge
+ $internal_name !~ /^(Get|Set)ThreadContext$/) # FIXME: Kludge
{
$#argument_types--;
}
diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm
index 533a793..5c90f91 100644
--- a/tools/winapi_check/winapi_options.pm
+++ b/tools/winapi_check/winapi_options.pm
@@ -61,7 +61,7 @@
"calling-convention" => { default => 0, parent => "local", description => "calling convention checking" },
"misplaced" => { default => 1, parent => "local", description => "check for misplaced functions" },
"statements" => { default => 0, parent => "local", description => "check for statements inconsistances" },
- "cross-call" => { default => 0, parent => "statements", description => "check for cross calling functions" },
+ "cross-call" => { default => 0, parent => "statements", description => "check for cross calling functions" },
"cross-call-win32-win16" => {
default => 0, parent => "cross-call", description => "check for cross calls between win32 and win16"
},
@@ -71,13 +71,16 @@
"debug-messages" => { default => 0, parent => "statements", description => "check for debug messages inconsistances" },
"documentation" => { default => 1, parent => "local", description => "check for documentation inconsistances\n" },
"documentation-width" => { default => 0, parent => "documentation", description => "check for documentation width inconsistances\n" },
+ "prototype" => { default => 0, parent => ["local", "headers"], description => "prototype checking" },
"global" => { default => 1, description => "global checking" },
- "declared" => { default => 1, parent => "global", description => "declared checking" },
+ "declared" => { default => 1, parent => "global", description => "declared checking" },
"implemented" => { default => 1, parent => "global", description => "implemented checking" },
"implemented-win32" => { default => 0, parent => "implemented", description => "implemented as win32 checking" },
"include" => { default => 1, parent => "global", description => "include checking" },
"headers" => { default => 0, parent => "global", description => "headers checking" },
+ "headers-duplicated" => { default => 0, parent => "headers", description => "duplicated function declarations checking" },
+ "headers-misplaced" => { default => 0, parent => "headers", description => "misplaced function declarations checking" },
"stubs" => { default => 0, parent => "global", description => "stubs checking" }
);
@@ -106,6 +109,8 @@
my $module = \${$self->{MODULE}};
my $global = \${$self->{GLOBAL}};
+ my @files;
+
if($wine_dir eq ".") {
$$global = 1;
} else {
@@ -151,8 +156,16 @@
if(defined($option)) {
my $key = $$option{key};
my $parser = $$option{parser};
- my $parent = $$option{parent};
my $refvalue = \${$self->{$key}};
+ my @parents = ();
+
+ if(defined($$option{parent})) {
+ if(ref($$option{parent}) eq "ARRAY") {
+ @parents = @{$$option{parent}};
+ } else {
+ @parents = $$option{parent};
+ }
+ }
if(defined($parser)) {
$$refvalue = &$parser($prefix,$value);
@@ -167,12 +180,23 @@
}
if((ref($$refvalue) eq "HASH" && $$refvalue->{active}) || $$refvalue) {
- while(defined($parent)) {
- my $parentkey = $options{$parent}{key};
- my $refparentvalue = \${$self->{$parentkey}};
-
- $$refparentvalue = 1;
- $parent = $options{$parent}{parent};
+ while($#parents >= 0) {
+ my @old_parents = @parents;
+ @parents = ();
+ foreach my $parent (@old_parents) {
+ my $parentkey = $options{$parent}{key};
+ my $refparentvalue = \${$self->{$parentkey}};
+
+ $$refparentvalue = 1;
+
+ if(defined($options{$parent}{parent})) {
+ if(ref($options{$parent}{parent}) eq "ARRAY") {
+ push @parents, @{$options{$parent}{parent}};
+ } else {
+ push @parents, $options{$parent}{parent};
+ }
+ }
+ }
}
}
next;
@@ -201,7 +225,7 @@
return undef;
}
- push @$c_files, $_;
+ push @files, $_;
}
}
@@ -209,30 +233,56 @@
return $self;
}
- my $c_paths;
- if($#$c_files == -1 || ($#$c_files == 0 && $$c_files[0] eq $wine_dir)) {
- $c_paths = ".";
+ my @paths = ();
+ my @c_files = ();
+ my @h_files = ();
+ foreach my $file (@files) {
+ if($file =~ /\.c$/) {
+ push @c_files, $file;
+ } elsif($file =~ /\.h$/) {
+ push @h_files, $file;
+ } else {
+ push @paths, $file;
+ }
+ }
+
+ if($#c_files == -1 && $#h_files == -1 &&
+ ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir)))
+ {
+ @paths = ".";
+ push @h_files, "$wine_dir/include";
} else {
- $c_paths = join(" ", @$c_files);
$$global = 0;
}
- my $h_paths = "$wine_dir/include $wine_dir/include/wine";
+ if($#paths != -1 || $#c_files != -1) {
+ my $c_command = "find " . join(" ", @paths, @c_files) . " -name \\*.c";
+ my %found;
+ @$c_files = sort(map {
+ s/^\.\/(.*)$/$1/;
+ if(defined($found{$_}) || /glue\.c|spec\.c$/) {
+ ();
+ } else {
+ $found{$_}++;
+ $_;
+ }
+ } split(/\n/, `$c_command`));
+ }
- @$c_files = sort(map {
- s/^.\/(.*)$/$1/;
- if(/glue\.c|spec\.c$/) {
- ();
- } else {
- $_;
- }
- } split(/\n/, `find $c_paths -name \\*.c`));
+ if($#h_files != -1) {
+ my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
+ my %found;
- @$h_files = sort(map {
- s/^.\/(.*)$/$1/;
- $_;
- } split(/\n/, `find $h_paths -name \\*.h`));
-
+ @$h_files = sort(map {
+ s/^\.\/(.*)$/$1/;
+ if(defined($found{$_})) {
+ ();
+ } else {
+ $found{$_}++;
+ $_;
+ }
+ } split(/\n/, `$h_command`));
+ }
return $self;
}