From d07a646f0fc9dc48cf3f0c2d568e6bd514f5d9ae Mon Sep 17 00:00:00 2001 From: Patrik Stridvall Date: Wed, 18 Jul 2001 20:09:12 +0000 Subject: [PATCH] Several additions and bug fixes. --- tools/winapi/config.pm | 21 +- tools/winapi/output.pm | 18 ++ tools/winapi/setup.pm | 4 +- tools/winapi/winapi_extract | 10 +- tools/winapi_check/modules.pm | 4 + tools/winapi_check/output.pm | 114 ----------- tools/winapi_check/win32/msvcrt.api | 6 +- tools/winapi_check/win32/ole32.api | 1 - tools/winapi_check/win32/shell32.api | 4 + tools/winapi_check/winapi.pm | 54 +----- tools/winapi_check/winapi_check | 350 +++++++++++++++++++--------------- tools/winapi_check/winapi_function.pm | 15 +- tools/winapi_check/winapi_global.pm | 3 +- tools/winapi_check/winapi_options.pm | 15 +- tools/winapi_check/winapi_parser.pm | 7 +- 15 files changed, 283 insertions(+), 343 deletions(-) delete mode 100644 tools/winapi_check/output.pm diff --git a/tools/winapi/config.pm b/tools/winapi/config.pm index 9b463789f7f..6e7aa8e1498 100644 --- a/tools/winapi/config.pm +++ b/tools/winapi/config.pm @@ -12,7 +12,7 @@ require Exporter; &file_absolutize &file_normalize &file_type &files_filter &file_skip &files_skip - &get_spec_files + &get_c_files &get_h_files &get_spec_files ); @EXPORT_OK = qw( $current_dir $wine_dir $winapi_dir $winapi_check_dir @@ -98,20 +98,27 @@ sub file_normalize { return $_; } -sub get_spec_files { - $output->progress("$wine_dir: searching for *.spec"); +sub _get_files { + my $extension = shift; + my $type = shift; + + $output->progress("$wine_dir: searching for *.$extension"); - my @spec_files = map { + my @files = map { s%^\./%%; s%^$wine_dir/%%; - if(file_type($_) eq "winelib") { + if(file_type($_) eq $type) { $_; } else { (); } - } split(/\n/, `find $wine_dir -name \\*.spec`); + } split(/\n/, `find $wine_dir -name \\*.$extension`); - return @spec_files; + return @files; } +sub get_c_files { return _get_files("c", @_); } +sub get_h_files { return _get_files("h", @_); } +sub get_spec_files { return _get_files("spec", @_); } + 1; diff --git a/tools/winapi/output.pm b/tools/winapi/output.pm index 6234d6c9d7a..1b461728d4f 100644 --- a/tools/winapi/output.pm +++ b/tools/winapi/output.pm @@ -34,11 +34,13 @@ sub new { my $progress = \${$self->{PROGRESS}}; my $last_progress = \${$self->{LAST_PROGRESS}}; + my $last_time = \${$self->{LAST_TIME}}; my $progress_count = \${$self->{PROGRESS_COUNT}}; my $prefix = \${$self->{PREFIX}}; $$progress = ""; $$last_progress = ""; + $$last_time = 0; $$progress_count = 0; $$prefix = ""; @@ -107,10 +109,26 @@ sub update_progress { sub progress { my $self = shift; my $progress = \${$self->{PROGRESS}}; + my $last_time = \${$self->{LAST_TIME}}; $$progress = shift; $self->update_progress; + $$last_time = 0; +} + +sub lazy_progress { + my $self = shift; + my $progress = \${$self->{PROGRESS}}; + my $last_time = \${$self->{LAST_TIME}}; + + $$progress = shift; + + my $time = time(); + if($time - $$last_time > 0) { + $self->update_progress; + $$last_time = $time; + } } sub prefix { diff --git a/tools/winapi/setup.pm b/tools/winapi/setup.pm index 15d2e163ca8..9c0961f3495 100644 --- a/tools/winapi/setup.pm +++ b/tools/winapi/setup.pm @@ -50,9 +50,7 @@ BEGIN { exit 1; } - push @INC, ($winapi_check_dir, $winapi_dir) if $tool eq "winapi_check"; - push @INC, ($winapi_dir, $winapi_check_dir) if $tool eq "winapi_extract"; - push @INC, ($winapi_dir, $winapi_check_dir) if $tool eq "winapi_fixup"; + push @INC, ($winapi_dir, $winapi_check_dir); } 1; diff --git a/tools/winapi/winapi_extract b/tools/winapi/winapi_extract index 981a4b40745..3680bdb90ea 100755 --- a/tools/winapi/winapi_extract +++ b/tools/winapi/winapi_extract @@ -55,7 +55,7 @@ my %module2type; { local $_; - foreach my $spec_file (get_spec_files) { + foreach my $spec_file (get_spec_files("winelib")) { my $module; my $type; @@ -177,13 +177,15 @@ sub statements_stub { } } -my @files = files_skip($options->c_files); +my @c_files = $options->c_files; +@c_files = files_skip(@c_files); +@c_files = files_filter("winelib", @c_files); my $progress_output; my $progress_current = 0; -my $progress_max = scalar(@files); +my $progress_max = scalar(@c_files); -foreach my $file (@files) { +foreach my $file (@c_files) { my %functions; $progress_current++; diff --git a/tools/winapi_check/modules.pm b/tools/winapi_check/modules.pm index 1252422efab..34f338e3db2 100644 --- a/tools/winapi_check/modules.pm +++ b/tools/winapi_check/modules.pm @@ -133,6 +133,10 @@ sub is_allowed_module_in_file { my $dir = $file; $dir =~ s/\/[^\/]*$//; + if($dir =~ m%^include%) { + return 1; + } + foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) { if($$spec_file2module{$spec_file} eq $module) { return 1; diff --git a/tools/winapi_check/output.pm b/tools/winapi_check/output.pm deleted file mode 100644 index c6347ee8525..00000000000 --- a/tools/winapi_check/output.pm +++ /dev/null @@ -1,114 +0,0 @@ -package output; - -use strict; - -my $stdout_isatty = -t STDOUT; -my $stderr_isatty = -t STDERR; - -sub new { - my $proto = shift; - my $class = ref($proto) || $proto; - my $self = {}; - bless ($self, $class); - - my $progress = \${$self->{PROGRESS}}; - my $last_progress = \${$self->{LAST_PROGRESS}}; - my $progress_count = \${$self->{PROGRESS_COUNT}}; - my $prefix = \${$self->{PREFIX}}; - - $$progress = ""; - $$last_progress = ""; - $$progress_count = 0; - $$prefix = ""; - - return $self; -} - - -sub show_progress { - my $self = shift; - my $progress = \${$self->{PROGRESS}}; - my $last_progress = \${$self->{LAST_PROGRESS}}; - my $progress_count = \${$self->{PROGRESS_COUNT}}; - - $$progress_count++; - - if($$progress_count > 0 && $$progress && $stderr_isatty) { - print STDERR $$progress; - $$last_progress = $$progress; - } -} - -sub hide_progress { - my $self = shift; - my $progress = \${$self->{PROGRESS}}; - my $last_progress = \${$self->{LAST_PROGRESS}}; - my $progress_count = \${$self->{PROGRESS_COUNT}}; - - $$progress_count--; - - if($$last_progress && $stderr_isatty) { - my $message; - for (1..length($$last_progress)) { - $message .= " "; - } - print STDERR $message; - undef $$last_progress; - } -} - -sub update_progress { - my $self = shift; - my $progress = \${$self->{PROGRESS}}; - my $last_progress = \${$self->{LAST_PROGRESS}}; - - my $prefix = ""; - my $suffix = ""; - if($$last_progress) { - for (1..length($$last_progress)) { - $prefix .= ""; - } - - my $diff = length($$last_progress)-length($$progress); - if($diff > 0) { - for (1..$diff) { - $suffix .= " "; - } - for (1..$diff) { - $suffix .= ""; - } - } - } - print STDERR $prefix . $$progress . $suffix; - $$last_progress = $$progress; -} - -sub progress { - my $self = shift; - my $progress = \${$self->{PROGRESS}}; - - $$progress = shift; - - $self->update_progress; -} - -sub prefix { - my $self = shift; - my $prefix = \${$self->{PREFIX}}; - - $$prefix = shift; -} - -sub write { - my $self = shift; - - my $message = shift; - - my $prefix = \${$self->{PREFIX}}; - - $self->hide_progress if $stdout_isatty; - print $$prefix . $message; - $self->show_progress if $stdout_isatty; -} - -1; diff --git a/tools/winapi_check/win32/msvcrt.api b/tools/winapi_check/win32/msvcrt.api index 6399e023e1c..354930357c8 100644 --- a/tools/winapi_check/win32/msvcrt.api +++ b/tools/winapi_check/win32/msvcrt.api @@ -14,8 +14,6 @@ MSVCRT_time_t WCHAR int long -size_t -time_t unsigned int unsigned long @@ -56,7 +54,6 @@ bad_typeid * char * char ** char *** -double * exception * int * jmp_buf @@ -66,13 +63,12 @@ struct _stat * struct _timeb * struct _utimbuf * struct _wfinddata_t * -struct tm * terminate_function -time_t * type_info * unexpected_function unsigned char * unsigned int * +unsigned long * va_list void * diff --git a/tools/winapi_check/win32/ole32.api b/tools/winapi_check/win32/ole32.api index cae3612523b..1540f51ebbe 100644 --- a/tools/winapi_check/win32/ole32.api +++ b/tools/winapi_check/win32/ole32.api @@ -84,7 +84,6 @@ REFGUID REFIID SNB STGMEDIUM * -WCHAR * WORD * void * void ** diff --git a/tools/winapi_check/win32/shell32.api b/tools/winapi_check/win32/shell32.api index 483c0e507b2..6f23acabec8 100644 --- a/tools/winapi_check/win32/shell32.api +++ b/tools/winapi_check/win32/shell32.api @@ -89,6 +89,10 @@ REFCLSID REFIID UINT * +%ptr # --forbidden + +int * + %str LPCSTR diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm index fd681cb91e1..e58e1fe6f5d 100644 --- a/tools/winapi_check/winapi.pm +++ b/tools/winapi_check/winapi.pm @@ -26,6 +26,10 @@ sub new { $$name = shift; my $path = shift; + if($$options->progress) { + $$output->progress("$path: searching for *.api"); + } + my @files = map { s%^\./%%; $_; @@ -33,6 +37,11 @@ sub new { foreach my $file (@files) { my $module = $file; + + if($$options->progress) { + $$output->lazy_progress("$file"); + } + $module =~ s/.*?\/([^\/]*?)\.api$/$1/; $self->parse_api_file($file,$module); } @@ -289,7 +298,7 @@ sub parse_spec_file { my $module_file; if($$options->progress) { - $$output->progress("$file"); + $$output->lazy_progress("$file"); } open(IN, "< $file") || die "$file: $!\n"; @@ -585,24 +594,6 @@ sub all_declared_types { return sort(keys(%$translate_argument)); } -sub found_type { - my $self = shift; - my $type_found = \%{$self->{TYPE_FOUND}}; - - my $name = shift; - - $$type_found{$name}++; -} - -sub type_found { - my $self = shift; - my $type_found= \%{$self->{TYPE_FOUND}}; - - my $name = shift; - - return $$type_found{$name}; -} - sub is_allowed_type_format { my $self = shift; my $type_format = \%{$self->{TYPE_FORMAT}}; @@ -734,13 +725,6 @@ sub all_functions_stub_in_module { return sort(keys(%{$$function_stub{$module}})); } -sub all_internal_functions_found { - my $self = shift; - my $function_found = \%{$self->{FUNCTION_FOUND}}; - - return sort(keys(%$function_found)); -} - sub function_internal_ordinal { my $self = shift; my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}}; @@ -892,24 +876,6 @@ sub is_function_stub_in_module { return $$function_stub{$module}{$name}; } -sub found_internal_function { - my $self = shift; - my $function_found = \%{$self->{FUNCTION_FOUND}}; - - my $name = shift; - - $$function_found{$name}++; -} - -sub internal_function_found { - my $self = shift; - my $function_found = \%{$self->{FUNCTION_FOUND}}; - - my $name = shift; - - return $$function_found{$name}; -} - ######################################################################## # class methods # diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check index 9f2469200e7..22d2ee941b3 100755 --- a/tools/winapi_check/winapi_check +++ b/tools/winapi_check/winapi_check @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -# Copyright 1999-2000 Patrik Stridvall +# Copyright 1999-2001 Patrik Stridvall # Note that winapi_check are using heuristics quite heavily. # So always remember that: @@ -20,10 +20,8 @@ BEGIN { } use config qw( - &file_absolutize &file_normalize - &file_type &files_filter - &file_skip &files_skip - &get_spec_files + &file_type &files_filter &files_skip + &get_h_files $current_dir $wine_dir $winapi_dir $winapi_check_dir ); use modules; @@ -66,31 +64,42 @@ if($options->global) { my $nativeapi = 'nativeapi'->new($options, $output, "$winapi_check_dir/nativeapi.dat", "$wine_dir/configure.in", "$wine_dir/include/config.h.in"); -my %includes; +my %declared_functions; + +my %include2info; { - my @files = map { - s/^.\/(.*)$/$1/; - $_; - } split(/\n/, `find . -name \\*.h`); - + my @files = get_h_files("winelib"); + + my $progress_current = 0; + my $progress_max = scalar(@files); + foreach my $file (@files) { + $progress_current++; + if($options->progress) { + $output->lazy_progress("$file: file $progress_current of $progress_max"); + } + my $file_dir = $file; - if(!($file_dir =~ s/(.*?)\/[^\/]*$/$1/)) { + if(!($file_dir =~ s%(.*?)/[^/]+$%$1%)) { $file_dir = "."; } - - $includes{$file} = { name => $file }; - open(IN, "< $file"); + $include2info{$file} = { name => $file }; + + open(IN, "< $wine_dir/$file"); while() { if(/^\s*\#\s*include\s*\"(.*?)\"/) { my $header = $1; - if(-e "$file_dir/$header") { - $includes{$file}{includes}{"$file_dir/$header"}++; - } elsif(-e "$file_dir/../$header") { # FIXME: This is not correct - $includes{$file}{includes}{"$file_dir/../$header"}++; # FIXME: This is not correct + if(-e "$wine_dir/$file_dir/$header") { + $include2info{$file}{includes}{"$file_dir/$header"}++; + } elsif(-e "$wine_dir/$file_dir/../$header") { + if($file_dir =~ m%^(.*?)/[^/]+$%) { + $include2info{$file}{includes}{"$1/$header"}++; + } else { + $include2info{$file}{includes}{"$header"}++; + } } elsif(-e "$wine_dir/include/$header") { - $includes{$file}{includes}{"include/$header"}++; + $include2info{$file}{includes}{"include/$header"}++; } else { $output->write("$file: #include \"$header\" is not a local include\n"); } @@ -102,18 +111,20 @@ my %includes; my @files2 = ("acconfig.h", "poppack.h", "pshpack1.h", "pshpack2.h", "pshpack4.h", "pshpack8.h", "storage.h", "ver.h"); foreach my $file2 (@files2) { - $includes{"include/$file2"}{used}++; + $include2info{"include/$file2"}{used}++; } } -my %declared_functions; +my @c_files = $options->c_files; +@c_files = files_skip(@c_files); +@c_files = files_filter("winelib", @c_files); -my @c_files = files_skip($options->c_files); -my @h_files = files_skip($options->h_files); +my @h_files = $options->h_files; +@h_files = files_skip(@h_files); +@h_files = files_filter("winelib", @h_files); -my $progress_output; -my $progress_current=0; -my $progress_max=scalar(@c_files); +my $progress_current = 0; +my $progress_max = scalar(@c_files); if($options->headers) { $progress_max += scalar(@h_files); @@ -125,77 +136,52 @@ if($options->headers) { if($options->progress) { $output->progress("$file: file $progress_current of $progress_max"); } - + my $found_function = sub { my $function = shift; - my $documentation_line = $function->documentation_line; - my $documentation = $function->documentation; + $output->prefix($function->prefix); + my $function_line = $function->function_line; - my $linkage = $function->linkage; - my $return_type = $function->return_type; - my $calling_convention = $function->calling_convention; my $internal_name = $function->internal_name; - my @argument_types = @{$function->argument_types}; - my @argument_names = @{$function->argument_names}; - my @argument_documentations = @{$function->argument_documentations}; my $statements = $function->statements; - - foreach my $winapi (@winapis) { - my $module = $winapi->function_internal_module($internal_name); - if(!defined($module)) { next } - - # FIXME: Not correct - my $external_name = $winapi->function_external_name($internal_name); - - if(defined($external_name)) { - $external_name = (split(/\s*&\s*/, $external_name))[0]; - } - - # FIXME: Kludge because of the THUNK variants - if(!defined($external_name)) { - next; - } - my $output_function = sub { - my $message = shift; + if($options->headers_misplaced && + !($function->is_win16 && $function->is_win32) && + (($function->is_win16 && $file =~ /^include\/[^\/]*$/) || + ($function->is_win32 && $file =~ /^include\/wine\/[^\/]*$/))) + { + $output->write("declaration misplaced\n"); + } - $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"; + if(!defined($statements)) { + my $previous_function = $declared_functions{$internal_name}; + if(!defined($previous_function)) { + $declared_functions{$internal_name} = $function; } 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 $file = $previous_function->file; + my $function_line = $previous_function->function_line; + $output->write("duplicate declaration (first declaration at $file:$function_line)\n"); } } }; - + my $found_preprocessor = sub { my $directive = shift; my $argument = shift; }; - + winapi_parser::parse_c_file $options, $output, $file, $found_function, $found_preprocessor; } } +my %module2functions = (); +my %type_found = (); + foreach my $file (@c_files) { my %functions = (); + my @includes = (); + my %needed_includes = (); my $file_module16 = $modules->allowed_modules_in_file("$current_dir/$file"); my $file_module32 = $modules->allowed_modules_in_file("$current_dir/$file"); @@ -210,14 +196,16 @@ foreach my $file (@c_files) { $file_dir = "."; } - my $file_type = file_type($file); - my $found_function = sub { my $function = shift; + $output->prefix($function->prefix); + my $internal_name = $function->internal_name; $functions{$internal_name} = $function; + my $declared_function = $declared_functions{$internal_name}; + my $documentation_line = $function->documentation_line; my $documentation = $function->documentation; my $linkage = $function->linkage; @@ -228,41 +216,36 @@ foreach my $file (@c_files) { my @argument_documentations = @{$function->argument_documentations}; my $statements = $function->statements; + my $module16 = $function->module16; + my $module32 = $function->module32; + my $external_name16 = $function->external_name16; my $external_name32 = $function->external_name32; - if($options->global) { - $win16api->found_type($return_type) if $options->win16; - $win32api->found_type($return_type) if $options->win32; - for my $argument (@argument_types) { - $win16api->found_type($argument) if $options->win16; - $win32api->found_type($argument) if $options->win32; + foreach my $module ($function->modules) { + $module2functions{$module}{$internal_name} = $function; + for my $type ($return_type, @argument_types) { + $type_found{$module}{$type}++; } } - if($options->declared) { - $win16api->found_internal_function($internal_name) if $options->win16; - $win32api->found_internal_function($internal_name) if $options->win32; + foreach my $module ($function->modules) { + $modules->found_module_in_dir($module, $file_dir); } - if($file_type eq "winelib") { - my $module16 = $function->module16; - my $module32 = $function->module32; - - foreach my $module ($function->modules) { - $modules->found_module_in_dir($module, $file_dir); + if($options->shared) { + if($win16api->is_shared_internal_function($internal_name) || + $win32api->is_shared_internal_function($internal_name)) + { + $output->write("is shared between Win16 and Win32\n"); } + } - $output->prefix("$file: " . $function->prefix); - - if($options->shared) { - if($win16api->is_shared_internal_function($internal_name) || - $win32api->is_shared_internal_function($internal_name)) - { - $output->write("is shared between Win16 and Win32\n"); - } - } + if(defined($declared_function)) { + $needed_includes{$declared_function->file}++; + } + if(1) { # FIXME: Not correct if(defined($external_name16)) { $external_name16 = (split(/\s*&\s*/, $external_name16))[0]; @@ -307,20 +290,15 @@ foreach my $file (@c_files) { 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(!$nativeapi->is_function($internal_name) && + !defined($declared_functions{$internal_name})) { - 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)?$/)) - { - $output->write("no prototype\n"); - } + $output->write("no prototype\n"); } } 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) || (!$nativeapi->is_function($external_name32) && !defined($declared_functions{$external_name32}))) { if(!defined($external_name32) || ($external_name32 !~ /^Dll(?: Install|CanUnloadNow|GetClassObject|GetVersion| @@ -379,17 +357,15 @@ foreach my $file (@c_files) { $nativeapi->found_conditional($_); if($options->config) { - if($file_type ne "application") { - if(!$nativeapi->is_conditional($_)) { - if(/^HAVE_/ && !/^HAVE_(IPX|MESAGL|BUGGY_MESAGL|WINE_CONSTRUCTOR)$/) - { - $output->write("$file: $_ is not declared as a conditional\n"); - } - } else { - $conditional++; - if(!$config) { - $output->write("$file: conditional $_ used but config.h is not included\n"); - } + if(!$nativeapi->is_conditional($_)) { + if(/^HAVE_/ && !/^HAVE_(IPX|MESAGL|BUGGY_MESAGL|WINE_CONSTRUCTOR)$/) + { + $output->write("$file: $_ is not declared as a conditional\n"); + } + } else { + $conditional++; + if(!$config) { + $output->write("$file: conditional $_ used but config.h is not included\n"); } } } @@ -407,21 +383,41 @@ foreach my $file (@c_files) { my $check_protection; my $check_local; if($argument =~ /^<(.*?)>$/) { - $header = $1; - if($file_type ne "application") { - $check_protection = 1; - } else { - $check_protection = 0; - } - $check_local = 0; - } elsif($argument =~ /^"(.*?)"$/) { - $header = $1; - $check_protection = 0; - $check_local = 1; + $header = $1; + $check_protection = 1; + $check_local = 0; + } elsif($argument =~ /^\"(.*?)\"$/) { + $header = $1; + $check_protection = 0; + $check_local = 1; + } else { + $output->write("$file: #$directive $argument: is unparsable\n"); + + $header = undef; + $check_protection = 0; + $check_local = 0; } - if($check_protection) { - if((-e "$wine_dir/include/$header" || -e "$file_dir/$header")) { + if(defined($header)) { + if(-e "$wine_dir/include/$header") { + push @includes, "include/$header"; + } elsif(-e "$file_dir/$header") { + push @includes, "$file_dir/$header"; + } elsif(-e "$file_dir/../$header") { + if($file_dir =~ m%^(.*?)/[^/]+$%) { + push @includes, "$1/$header"; + } else { + push @includes, "$header"; + } + } elsif($header eq "controls.h") { # FIXME: Kludge + push @includes, "dlls/user/controls.h"; + } elsif($check_local) { + $output->write("$file: #include \"$header\": file not found\n"); + } + } + + if($check_protection && $header) { + if((-e "$wine_dir/include/$header" || -e "$wine_dir/$file_dir/$header")) { if($header !~ /^ctype.h$/) { $output->write("$file: #include \<$header\> is a local include\n"); } @@ -448,26 +444,40 @@ foreach my $file (@c_files) { } } - if($check_local) { + if($check_local && $header) { if(-e "$file_dir/$header") { - $includes{"$file_dir/$header"}{used}++; - foreach my $name (keys(%{$includes{"$file_dir/$header"}{includes}})) { - $includes{$name}{used}++; + if($file_dir ne ".") { + $include2info{"$file_dir/$header"}{used}++; + foreach my $name (keys(%{$include2info{"$file_dir/$header"}{includes}})) { + $include2info{$name}{used}++; + } + } else { + $include2info{"$header"}{used}++; + foreach my $name (keys(%{$include2info{"$header"}{includes}})) { + $include2info{$name}{used}++; + } } - } elsif(-e "$file_dir/../$header") { # FIXME: Kludge - $includes{"$file_dir/../$header"}{used}++; # FIXME: This is not correct - foreach my $name (keys(%{$includes{"$file_dir/../$header"}{includes}})) { # FIXME: This is not correct - $includes{$name}{used}++; + } elsif(-e "$wine_dir/$file_dir/../$header") { + if($file_dir =~ m%^(.*?)/[^/]+$%) { + $include2info{"$1/$header"}{used}++; + foreach my $name (keys(%{$include2info{"$1/$header"}{includes}})) { + $include2info{$name}{used}++; + } + } else { + $include2info{"$header"}{used}++; + foreach my $name (keys(%{$include2info{"$header"}{includes}})) { + $include2info{$name}{used}++; + } } } elsif($header eq "controls.h") { # FIXME: Kludge - $includes{"dlls/user/$header"}{used}++; - foreach my $name (keys(%{$includes{"dlls/user/$header"}{includes}})) { - $includes{$name}{used}++; + $include2info{"dlls/user/$header"}{used}++; + foreach my $name (keys(%{$include2info{"dlls/user/$header"}{includes}})) { + $include2info{$name}{used}++; } } elsif(-e "$wine_dir/include/$header") { - $includes{"include/$header"}{used}++; - foreach my $name (keys(%{$includes{"include/$header"}{includes}})) { - $includes{$name}{used}++; + $include2info{"include/$header"}{used}++; + foreach my $name (keys(%{$include2info{"include/$header"}{includes}})) { + $include2info{$name}{used}++; } } else { $output->write("$file: #include \"$header\" is not a local include\n"); @@ -481,10 +491,32 @@ foreach my $file (@c_files) { if($options->config_unnessary) { if($config && $conditional == 0) { - $output->write("$file: includes config.h but do not use any conditionals\n"); + $output->write("$file: include2info config.h but do not use any conditionals\n"); } } + if($options->headers_needed) { + my %includes2; + foreach my $include (@includes) { + $includes2{$include}++; + foreach my $include (keys(%{$include2info{$include}{includes}})) { + $includes2{$include}++; + } + } + foreach my $needed_include (sort(keys(%needed_includes))) { + my $found = 0; + foreach my $include (sort(keys(%includes2))) { + if($needed_include eq $include) { + $found = 1; + } + } + if(!$found) { + $output->write("$file: file '$needed_include' needed but not included\n"); + } + } + } + + winapi_local::check_file $options, $output, $file, \%functions; } @@ -523,8 +555,14 @@ if($options->declared) { if($options->declared) { foreach my $winapi (@winapis) { if(!$winapi->is_module($module)) { next; } + my $functions = $module2functions{$module}; foreach my $internal_name ($winapi->all_internal_functions_in_module($module)) { - if(!$winapi->internal_function_found($internal_name)) { + my $function = $functions->{$internal_name}; + if(!defined($function) && !$nativeapi->is_function($internal_name) && + !($module eq "user" && $internal_name =~ + /^(?:GlobalAddAtomA|GlobalDeleteAtom|GlobalFindAtomA| + GlobalGetAtomNameA|lstrcmpiA)$/x)) + { $output->write("*.c: $module: $internal_name: " . "function declared but not implemented or declared external\n"); } @@ -538,9 +576,9 @@ if($options->declared) { if($options->global) { winapi_documentation::report_documentation $options, $output; - if($options->headers) { - foreach my $name (sort(keys(%includes))) { - if(!$includes{$name}{used}) { + if($options->headers_unused) { + foreach my $name (sort(keys(%include2info))) { + if(!$include2info{$name}{used}) { if($options->include) { $output->write("*.c: $name: include file is never used\n"); } @@ -548,8 +586,8 @@ if($options->global) { } } - winapi_global::check $options, $output, $win16api, $nativeapi if $options->win16; - winapi_global::check $options, $output, $win32api, $nativeapi if $options->win32; + winapi_global::check $options, $output, $win16api, $nativeapi, \%type_found if $options->win16; + winapi_global::check $options, $output, $win32api, $nativeapi, \%type_found if $options->win32; $modules->global_report; $nativeapi->global_report; diff --git a/tools/winapi_check/winapi_function.pm b/tools/winapi_check/winapi_function.pm index b43f7abe947..a43ff57669e 100644 --- a/tools/winapi_check/winapi_function.pm +++ b/tools/winapi_check/winapi_function.pm @@ -22,6 +22,13 @@ sub new { } ######################################################################## +# is_win +# + +sub is_win16 { my $self = shift; return defined($self->_module($win16api, @_)); } +sub is_win32 { my $self = shift; return defined($self->_module($win32api, @_)); } + +######################################################################## # external_name # @@ -190,6 +197,7 @@ sub prefix { my $module32 = $self->module32; my $file = $self->file; + my $function_line = $self->function_line; my $return_type = $self->return_type; my $internal_name = $self->internal_name; my $calling_convention = $self->calling_convention; @@ -208,7 +216,12 @@ sub prefix { push @modules, $module; $used{$module}++; } - $prefix .= "$file: "; + $prefix .= "$file:"; + if(defined($function_line)) { + $prefix .= "$function_line: "; + } else { + $prefix .= "<>: "; + } if($#modules >= 0) { $prefix .= join(" & ", @modules) . ": "; } else { diff --git a/tools/winapi_check/winapi_global.pm b/tools/winapi_check/winapi_global.pm index b9261019b84..72490620c8b 100644 --- a/tools/winapi_check/winapi_global.pm +++ b/tools/winapi_check/winapi_global.pm @@ -7,12 +7,13 @@ sub check { my $output = shift; my $winapi = shift; my $nativeapi = shift; + my $type_found = shift; my $winver = $winapi->name; if($options->argument) { foreach my $type ($winapi->all_declared_types) { - if(!$winapi->type_found($type) && !$winapi->is_limited_type($type) && $type ne "CONTEXT86 *") { + if(!$$type_found{$type} && !$winapi->is_limited_type($type) && $type ne "CONTEXT86 *") { $output->write("*.c: $winver: "); $output->write("type ($type) not used\n"); } diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm index e137f0097c7..21b9f2a950b 100644 --- a/tools/winapi_check/winapi_options.pm +++ b/tools/winapi_check/winapi_options.pm @@ -118,9 +118,12 @@ my %options = ( "implemented" => { default => 0, parent => "local", 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" => { default => 0, 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" }, + "headers-needed" => { default => 1, parent => "headers", description => "headers needed checking" }, + "headers-unused" => { default => 0, parent => "headers", description => "headers unused checking" }, ); my %short_options = ( @@ -147,6 +150,7 @@ sub new { my $h_files = \@{$self->{H_FILES}}; my $module = \${$self->{MODULE}}; my $global = \${$self->{GLOBAL}}; + my $headers = \${$self->{HEADERS}}; my @files; @@ -285,11 +289,14 @@ sub new { } } + if($#h_files >= 0) { + $$headers = 1; + } + if($#c_files == -1 && $#h_files == -1 && ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir))) { @paths = "."; - push @h_files, "$wine_dir/include"; } else { $$global = 0; } @@ -308,8 +315,8 @@ sub new { } split(/\n/, `$c_command`)); } - if($#h_files != -1) { - my $h_command = "find " . join(" ", @h_files) . " -name \\*.h"; + if($#paths != -1 || $#h_files != -1) { + my $h_command = "find " . join(" ", @paths, @h_files) . " -name \\*.h"; my %found; @$h_files = sort(map { diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm index 3ecda0473a1..8e99f839ab9 100644 --- a/tools/winapi_check/winapi_parser.pm +++ b/tools/winapi_check/winapi_parser.pm @@ -62,8 +62,9 @@ sub parse_c_file { $function->file($file); $function->debug_channels([@$debug_channels]); - $function->documentation($documentation); $function->documentation_line($documentation_line); + $function->documentation($documentation); + $function->function_line($function_line); $function->linkage($linkage); $function->return_type($return_type); $function->calling_convention($calling_convention); @@ -255,8 +256,8 @@ sub parse_c_file { if($internal_name && $level == 0) { &$function_end; } - next; - } elsif(/(extern\s+|static\s+)?((struct\s+|union\s+|enum\s+)?\w+((\s*\*)+\s*|\s+)) + next; + } elsif(/(extern\s+|static\s+)?((struct\s+|union\s+|enum\s+|signed\s+|unsigned\s+)?\w+((\s*\*)+\s*|\s+)) ((__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK)\s+)? (\w+(\(\w+\))?)\s*\(([^\)]*)\)\s*(\{|\;)/sx) { -- 2.11.4.GIT