- 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.
This commit is contained in:
Patrik Stridvall 2000-05-23 23:37:51 +00:00 committed by Alexandre Julliard
parent 4615e29c58
commit 0d9748159d
9 changed files with 256 additions and 110 deletions

View file

@ -145,14 +145,21 @@ files
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 @@ dlls/user
memory
windows
% dlls/user/ddeml.spec
dlls/user
misc
% dlls/user/user.spec
controls
@ -393,10 +405,6 @@ dlls/x11drv
% if1632/comm.spec
% if1632/ddeml.spec
misc
% if1632/dispdib.spec
graphics
@ -414,16 +422,6 @@ relay32
scheduler
win32
% if1632/ole2conv.spec
% if1632/ole2nls.spec
ole
% if1632/ole2prox.spec
% if1632/ole2thk.spec
% if1632/system.spec
misc

View file

@ -52,6 +52,11 @@ sub new {
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 {

View file

@ -16,6 +16,7 @@ _sysconf
_xmknod
_xstat
abs
accept
access
acos
asctime
@ -26,14 +27,18 @@ atexit
atof
atoi
atol
bind
bsearch
bzero
calloc
ceil
cfgetospeed
chmod
clock
close
closedir
closesocket
connect
cos
cosh
ctime
@ -66,23 +71,39 @@ fputs
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 @@ kill
labs
ldexp
ldiv
listen
localtime
log
log10
@ -121,6 +143,8 @@ modf
mprotect
msync
munmap
ntohl
ntohs
open
opendir
perror
@ -128,6 +152,7 @@ pipe
poll
pow
printf
putc
putchar
putenv
puts
@ -137,19 +162,25 @@ rand
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
sin
sinh
sleep
socket
snprintf
sprintf
sqrt

View file

@ -1,3 +1,8 @@
%double
GLclampd
GLdouble
%long
BOOL
@ -6,9 +11,7 @@ FLOAT
GLbitfield
GLboolean
GLbyte
GLclampd
GLclampf
GLdouble
GLenum
GLfloat
GLint

View file

@ -215,6 +215,7 @@ sub parse_spec_file {
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 @@ sub parse_spec_file {
$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 @@ sub function_calling_convention {
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}};

View file

@ -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 $modules = 'modules'->new($options, $output, $wine_dir, $current_dir, \&file_
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 @@ if($options->headers) {
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 @@ foreach my $file ($options->c_files) {
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 @@ foreach my $file ($options->c_files) {
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 @@ foreach my $file ($options->c_files) {
$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 @@ foreach my $file ($options->c_files) {
}
}
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;
}
}

View file

@ -66,15 +66,26 @@ sub calling_convention {
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 {

View file

@ -13,23 +13,23 @@ sub check_function {
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 @@ sub check_function {
}
}
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 @@ sub check_function {
}
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--;
}

View file

@ -61,7 +61,7 @@ my %options = (
"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 @@ my %options = (
"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 @@ sub new {
my $module = \${$self->{MODULE}};
my $global = \${$self->{GLOBAL}};
my @files;
if($wine_dir eq ".") {
$$global = 1;
} else {
@ -151,8 +156,16 @@ sub new {
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 @@ sub new {
}
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 @@ sub new {
return undef;
}
push @$c_files, $_;
push @files, $_;
}
}
@ -209,30 +233,56 @@ sub new {
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`));
@$h_files = sort(map {
s/^.\/(.*)$/$1/;
$_;
} split(/\n/, `find $h_paths -name \\*.h`));
if($#h_files != -1) {
my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
my %found;
@$h_files = sort(map {
s/^\.\/(.*)$/$1/;
if(defined($found{$_})) {
();
} else {
$found{$_}++;
$_;
}
} split(/\n/, `$h_command`));
}
return $self;
}