#!/usr/bin/perl -w
-# Copyright 1999 Patrik Stridvall
+# Copyright 1999-2002 Patrik Stridvall
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# 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;
-my $wine_dir;
-my $winapi_check_dir;
-
BEGIN {
+ $0 =~ m%^(.*?/?tools)/winapi_check/winapi_check$%;
+ require "$1/winapi/setup.pm";
+}
- if($0 =~ /^((.*?)\/?tools\/winapi_check)\/winapi_check$/)
- {
- $winapi_check_dir = $1;
- if($2 ne "")
- {
- $wine_dir = $2;
- } else {
- $wine_dir = ".";
- }
+use config qw(
+ &files_filter &files_skip
+ &get_h_files
+ $current_dir $wine_dir
+);
+use output qw($output);
+use winapi_check_options qw($options);
+
+BEGIN {
+ if($options->progress) {
+ $output->enable_progress;
+ } else {
+ $output->disable_progress;
}
- @INC = ($winapi_check_dir);
-
- require "nativeapi.pm";
- require "output.pm";
- require "preprocessor.pm";
- require "winapi.pm";
- require "winapi_function.pm";
- require "winapi_local.pm";
- require "winapi_global.pm";
- require "winapi_options.pm";
- require "winapi_parser.pm";
-
- import nativeapi;
- import output;
- import preprocessor;
- import winapi;
- import winapi_function;
- import winapi_local;
- import winapi_global;
- import winapi_options;
- import winapi_parser;
}
-my $options = winapi_options->new(\@ARGV, $wine_dir);
-if($options->help) {
- $options->show_help;
- exit;
-}
+use modules qw($modules);
+use nativeapi qw($nativeapi);
+use winapi qw($win16api $win32api @winapis);
-my $output = 'output'->new;
+use preprocessor;
+use type;
+use util qw(&is_subset);
+use winapi_documentation;
+use winapi_function;
+use winapi_local;
+use winapi_global;
+use winapi_parser;
-my $win16api = 'winapi'->new($options, $output, "win16", "$winapi_check_dir/win16");
-my $win32api = 'winapi'->new($options, $output, "win32", "$winapi_check_dir/win32");
-'winapi'->read_spec_files($wine_dir, $win16api, $win32api);
+my %include2info;
-my $nativeapi = 'nativeapi'->new($output, "$winapi_check_dir/nativeapi.dat", "$wine_dir/configure.in", "$wine_dir/include/config.h.in");
+if ($options->global) {
+ my @files = get_h_files("winelib");
-for my $name ($win32api->all_functions) {
- my $module16 = $win16api->function_module($name);
- my $module32 = $win32api->function_module($name);
-
- if(defined($module16)) {
- $win16api->found_shared_function($name);
- $win32api->found_shared_function($name);
-
- if($options->shared) {
- $output->write("*.spec: $name: is shared between $module16 (Win16) and $module32 (Win32)\n");
- }
- }
-}
+ my $progress_current = 0;
+ my $progress_max = scalar(@files);
-my %includes;
-{
- my @files = map {
- s/^.\/(.*)$/$1/;
- $_;
- } split(/\n/, `find . -name \\*.h`);
-
foreach my $file (@files) {
+ $progress_current++;
+ $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(<IN>) {
if(/^\s*\#\s*include\s*\"(.*?)\"/) {
my $header = $1;
- if(-e "$file_dir/$header") {
- $includes{$file}{includes}{"$file_dir/$header"}++;
+ 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"}++;
- } else {
- $output->write("$file: #include \"$header\" is not a local include ($file_dir)\n");
+ $include2info{$file}{includes}{"include/$header"}++;
+ } elsif ($header ne "config.h") {
+ $output->write("$file: #include \"$header\" is not a local include\n");
}
}
}
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 @h_files = $options->h_files;
+@h_files = files_skip(@h_files);
+@h_files = files_filter("winelib", @h_files);
+
+my $all_modules = 0;
+my %complete_module;
+if($options->global) {
+ my @complete_modules = $modules->complete_modules(\@c_files);
+
+ foreach my $module (@complete_modules) {
+ $complete_module{$module}++;
+ }
+
+ my $all_modules = 1;
+ foreach my $module ($modules->all_modules) {
+ if(!$complete_module{$module}) {
+ $all_modules = 0;
+ if($wine_dir eq ".") {
+ $output->write("*.c: module $module is not complete\n");
+ }
+ }
+ }
+}
+
+if(1) {
+ foreach my $winapi (@winapis) {
+ foreach my $broken_forward ($winapi->all_broken_forwards) {
+ (my $module, my $external_name, my $forward_module, my $forward_external_name) = @$broken_forward;
+ if($complete_module{$forward_module}) {
+ $output->write("$module.spec: forward is broken: $external_name => $forward_module.$forward_external_name\n");
+ }
+ }
+ }
+}
+
+my $progress_current = 0;
+my $progress_max = scalar(@c_files);
-my $progress_output;
-my $progress_current=0;
-my $progress_max=scalar($options->c_files);
+my %declared_functions;
if($options->headers) {
- $progress_max += scalar($options->h_files);
+ $progress_max += scalar(@h_files);
- foreach my $file ($options->h_files) {
+ foreach my $file (@h_files) {
my %functions;
-
+
$progress_current++;
- if($options->progress) {
- $output->progress("$file: file $progress_current of $progress_max");
- }
-
+ $output->progress("$file: file $progress_current of $progress_max");
+
+ my $found_c_comment = sub {
+ my $begin_line = shift;
+ my $end_line = shift;
+ my $comment = shift;
+
+ if(0) {
+ if($begin_line == $end_line) {
+ $output->write("$file:$begin_line: $comment\n");
+ } else {
+ $output->write("$file:$begin_line-$end_line: \\\n$comment\n");
+ }
+ }
+ };
+
+ my $found_cplusplus_comment = sub {
+ my $line = shift;
+ my $comment = shift;
+
+ if($options->comments_cplusplus) {
+ $output->write("$file:$line: C++ comments not allowed: $comment\n");
+ }
+ };
+
+ my $create_function = sub {
+ return 'winapi_function'->new;
+ };
+
my $found_function = sub {
- my $documentation = shift;
- my $linkage = shift;
- my $return_type = shift;
- my $calling_convention = shift;
- my $name = shift;
- my $refarguments = shift;
- my @arguments = @$refarguments;
- my $statements = shift;
-
- $declared_functions{$name}++;
+ my $function = shift;
+
+ my $internal_name = $function->internal_name;
+
+ $output->progress("$file (file $progress_current of $progress_max): $internal_name");
+ $output->prefix_callback(sub { return $function->prefix; });
+
+ my $function_line = $function->function_line;
+ my $linkage = $function->linkage;
+ my $external_name = $function->external_name;
+ my $statements = $function->statements;
+
+ 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");
+ }
+
+ if(defined($external_name) && !defined($statements) &&
+ ($linkage eq "" || $linkage eq "extern"))
+ {
+ my $previous_function = $declared_functions{$internal_name};
+ if(!defined($previous_function)) {
+ $declared_functions{$internal_name} = $function;
+ } elsif($options->headers_duplicated) {
+ my $file = $previous_function->file;
+ my $function_line = $previous_function->function_line;
+ if($file =~ /\.h$/) {
+ $output->write("duplicate declaration (first declaration at $file:$function_line)\n");
+ }
+ }
+ }
+ $output->prefix("");
+ };
+
+ my $create_type = sub {
+ return 'type'->new;
};
-
+
+ my $found_type = sub {
+ my $type = shift;
+ };
+
my $found_preprocessor = sub {
my $directive = shift;
my $argument = shift;
};
-
- winapi_parser::parse_c_file $options, $output, $file, $found_function, $found_preprocessor;
+
+ &winapi_parser::parse_c_file($file, {
+ c_comment_found => $found_c_comment,
+ cplusplus_comment_found => $found_cplusplus_comment,
+ function_create => $create_function,
+ function_found => $found_function,
+ type_create => $create_type,
+ type_found => $found_type,
+ preprocessor_found => $found_preprocessor
+ });
}
}
-my %comment_width;
-my %module_pseudo_stub_count16;
-my %module_pseudo_stub_count32;
+my %module2functions = ();
-foreach my $file ($options->c_files) {
+foreach my $file (@c_files) {
my %functions = ();
+ my %includes = ();
+
+ $includes{$file}++;
+
+ my $file_module16 = $modules->allowed_modules_in_file("$current_dir/$file");
+ my $file_module32 = $modules->allowed_modules_in_file("$current_dir/$file");
$progress_current++;
- if($options->progress) {
- $output->progress("$file: file $progress_current of $progress_max");
- }
+ $output->progress("$file (file $progress_current of $progress_max)");
my $file_dir = $file;
if(!($file_dir =~ s/(.*?)\/[^\/]*$/$1/)) {
$file_dir = ".";
}
- my $file_type;
- if($file_dir =~ /^(libtest|program|rc|tools)/ ||
- $file =~ /dbgmain\.c$/ ||
- $file =~ /wineclipsrv\.c$/) # FIXME: Kludge
- {
- $file_type = "application";
- } elsif($file_dir =~ /^(debug|miscemu)/) {
- $file_type = "emulator";
- } else {
- $file_type = "library";
- }
-
- my $found_function = sub {
- my $documentation = shift;
- my $linkage = shift;
- my $return_type = shift;
- my $calling_convention = shift;
- my $name = shift;
- my $refarguments = shift;
- my @arguments = @$refarguments;
- my $statements = shift;
-
- if($options->global) {
- $win16api->found_type($return_type) if $options->win16;
- $win32api->found_type($return_type) if $options->win32;
- for my $argument (@arguments) {
- $win16api->found_type($argument) if $options->win16;
- $win32api->found_type($argument) if $options->win32;
+ my $found_c_comment = sub {
+ my $begin_line = shift;
+ my $end_line = shift;
+ my $comment = shift;
+
+ if(0) {
+ if($begin_line == $end_line) {
+ $output->write("$file:$begin_line: $comment\n");
+ } else {
+ $output->write("$file:$begin_line-$end_line: \\\n$comment\n");
}
-
- $win16api->found_function($name) if $options->win16;
- $win32api->found_function($name) if $options->win32;
}
-
- if($options->local && $file_type ne "application") {
- my $module16 = $win16api->function_module($name);
- my $module32 = $win32api->function_module($name);
-
- my $function = 'winapi_function'->new;
- $functions{$name} = $function;
-
- $function->documentation($documentation);
- $function->linkage($linkage);
- $function->file($file);
- $function->return_type($return_type);
- $function->calling_convention($calling_convention);
- $function->name($name);
- $function->arguments([@arguments]);
- $function->statements($statements);
- $function->module16($module16);
- $function->module32($module32);
-
- my $output_module = sub {
- my $module = shift;
- return sub {
- my $msg = shift;
- $output->write("$file: $module: $return_type ");
- $output->write("$calling_convention ") if $calling_convention;
- $output->write("$name(" . join(",", @arguments) . "): $msg\n");
+ };
+
+ my $found_cplusplus_comment = sub {
+ my $line = shift;
+ my $comment = shift;
+
+ if($options->comments_cplusplus) {
+ $output->write("$file:$line: C++ comments not allowed: $comment\n");
+ }
+ };
+
+ my $create_function = sub {
+ return 'winapi_function'->new;
+ };
+
+ my $found_function = sub {
+ my $function = shift;
+
+ my $internal_name = $function->internal_name;
+ $functions{$internal_name} = $function;
+
+ $output->progress("$file (file $progress_current of $progress_max): $internal_name");
+ $output->prefix_callback(sub { return $function->prefix; });
+
+ my $declared_function = $declared_functions{$internal_name};
+
+ my $documentation_line = $function->documentation_line;
+ my $documentation = $function->documentation;
+ my $linkage = $function->linkage;
+ my $return_type = $function->return_type;
+ my $calling_convention = $function->calling_convention;
+ my $statements = $function->statements;
+
+ my $module16 = $function->module16;
+ my $module32 = $function->module32;
+
+ my $external_name = $function->external_name;
+ my $external_name16 = $function->external_name16;
+ my $external_name32 = $function->external_name32;
+
+ if(defined($external_name) && !defined($statements) &&
+ ($linkage eq "" || $linkage eq "extern"))
+ {
+ my $previous_function = $declared_functions{$internal_name};
+ if(!defined($previous_function)) {
+ $declared_functions{$internal_name} = $function;
+ } else {
+ my $file = $previous_function->file;
+ my $function_line = $previous_function->function_line;
+
+ my $header = $file;
+ $header =~ s%^(include|$file_dir)/%%;
+ if($header !~ m%^msvcrt/% || $file_dir =~ m%^dlls/msvcrt%) {
+ $output->write("duplicate declaration (first declaration at $file:$function_line)\n");
}
- };
- my $output16 = &$output_module($module16);
- my $output32 = &$output_module($module32);
-
- if($options->headers) {
- if(!$declared_functions{$name}) {
- if($options->win16 && $options->report_module($module16)) {
- &$output16("no prototype");
- }
- if($options->win32 && $options->report_module($module32)) {
- &$output32("no prototype");
- }
- }
}
+ }
- if($options->argument) {
- if($options->win16 && $options->report_module($module16)) {
- winapi_local::check_function $options, $output16,
- $return_type, $calling_convention, $name, [@arguments], $win16api;
- }
- if($options->win32 && $options->report_module($module32)) {
- winapi_local::check_function $options, $output32,
- $return_type, $calling_convention, $name, [@arguments], $win32api;
- }
+ if ($options->global) {
+ foreach my $module ($function->modules) {
+ $module2functions{$module}{$internal_name} = $function;
}
- if($options->misplaced) {
- my $module;
- if($file =~ m'^dlls/(.*)/') {
- $module = $1;
- }
+ }
- if($options->win16 && $options->report_module($module16)) {
- if(!defined($module) || $module ne $module16) {
- &$output16("function misplaced");
- }
+ 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");
+ }
+ }
+
+ if($options->headers && $options->headers_needed &&
+ defined($declared_function) && defined($external_name) &&
+ defined($statements))
+ {
+ my $needed_include = $declared_function->file;
+
+ if(!defined($includes{$needed_include})) {
+ my $header = $needed_include;
+ $header =~ s%^(include|$file_dir)/%%;
+ if($header !~ m%^msvcrt/% || $file_dir =~ m%^dlls/msvcrt%) {
+ $output->write("prototype not included: #include \"$header\" is needed\n");
}
-
- if($options->win32 && $options->report_module($module32)) {
- if(!defined($module) || $module ne $module32) {
- &$output32("function misplaced");
- }
- }
}
- if($options->cross_call) {
- local $_ = $statements;
- my $called_function_names = {};
- while(defined($_)) {
- if(/(\w+)\((.*?)\)/) {
- $_ = $';
- my $called_name = $1;
- if($called_name !~ /^if|for|while|switch|sizeof$/) {
- $functions{$name}->function_called($called_name);
- if(!defined($functions{$called_name})) {
- $functions{$called_name} = 'function'->new;
+ }
+
+ if($options->local && $options->argument && defined($statements)) {
+ &winapi_local::check_function($function);
+ }
+
+ if($options->local && $options->statements && defined($statements)) {
+ &winapi_local::check_statements(\%functions, $function);
+ }
+
+ if($options->local && $options->documentation &&
+ (defined($module16) || defined($module32)) &&
+ $linkage eq "" && defined($statements))
+ {
+ &winapi_documentation::check_documentation($function);
+ }
+
+ if(1) {
+ # FIXME: Not correct
+ if(defined($external_name16)) {
+ $external_name16 = (split(/\s*&\s*/, $external_name16))[0];
+ }
+
+ # FIXME: Not correct
+ if(defined($external_name32)) {
+ $external_name32 = (split(/\s*&\s*/, $external_name32))[0];
+ }
+
+ if($options->local && $options->misplaced &&
+ $linkage ne "extern" && defined($statements))
+ {
+ if($options->win16 && $options->report_module($module16))
+ {
+ if($file ne "library/port.c" &&
+ !$nativeapi->is_function($internal_name) &&
+ !is_subset($module16, $file_module16))
+ {
+ foreach my $module16 (split(/\s*&\s*/, $module16)) {
+ if(!$win16api->is_function_stub($module16, $internal_name)) {
+ $output->write("is misplaced ($module16)\n");
}
- $functions{$called_name}->function_called_by($name);
}
- } else {
- undef $_
}
}
- }
- if($options->stubs) {
- if(defined($statements) && $statements =~ /FIXME[^;]*stub/) {
- if($options->win16 && $options->report_module($module16)) {
- foreach my $module (split(/ \& /, $module16)) {
- $module_pseudo_stub_count16{$module}++;
- }
- }
- if($options->win32 && $options->report_module($module32)) {
- foreach my $module (split(/ \& /, $module32)) {
- $module_pseudo_stub_count32{$module}++;
+ if($options->win32 && $options->report_module($module32))
+ {
+ if($file ne "library/port.c" &&
+ !$nativeapi->is_function($internal_name) &&
+ !is_subset($module32, $file_module32))
+ {
+ foreach my $module32 (split(/\s*&\s*/, $module32)) {
+ if(!$win32api->is_function_stub($module32, $internal_name)) {
+ $output->write("is misplaced ($module32)\n");
+ }
}
}
}
}
-
- if($options->documentation && (defined($module16) || defined($module32)) &&
- $linkage ne "extern" && $statements ne "")
- {
- my $name1;
- my $name2;
-
- if(defined($module16) && !defined($module32)) {
- my @uc_modules16 = split(/\s*\&\s*/, uc($module16));
- push @uc_modules16, "WIN16";
-
- $name1 = $name;
- foreach my $uc_module16 (@uc_modules16) {
- if($name1 =~ s/^$uc_module16\_//) { last; }
- }
-
- # FIXME: This special case is becuase of a very ugly kludge that should be fixed IMHO
- $name2 = $name1;
- $name2 = s/^(.*?)16_fn(.*?)$/$116_$2/;
- } elsif(!defined($module16) && defined($module32)) {
- my @uc_modules32 = split(/\s*\&\s*/, uc($module32));
- $name1 = $name;
- foreach my $uc_module32 (@uc_modules32) {
- if($name1 =~ s/^$uc_module32\_//) { last; }
- }
-
- $name2 = $name1;
- $name2 =~ s/AW$//;
- } else {
- my @uc_modules = split(/\s*\&\s*/, uc($module16));
- push @uc_modules, split(/\s*\&\s*/, uc($module32));
-
- $name1 = $name;
- foreach my $uc_module (@uc_modules) {
- if($name1 =~ s/^$uc_module\_//) { last; }
+ if($options->local && $options->headers && $options->prototype) {
+ if($options->win16 && $options->report_module($module16)) {
+ if(!$nativeapi->is_function($internal_name) &&
+ !defined($declared_functions{$internal_name}))
+ {
+ $output->write("no prototype\n");
}
-
- $name2 = $name1;
- }
-
- if($documentation !~ /\b($name|$name1|$name2)\b/) {
- $output->write("$file: $name: \\\n");
- $output->write("$documentation\n");
}
- if($options->documentation_width) {
- if($documentation =~ /(\/\**)/) {
- my $width = length($1);
-
- $comment_width{$width}++;
- if($width <= 65 || $width >= 81) {
- $output->write("$file: $name: comment is $width columns wide\n");
+ if($options->win32 && $options->report_module($module32)) {
+ 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|
+ RegisterServer|RegisterServerEx|UnregisterServer)|DriverProc$/x &&
+ $internal_name !~ /^COMCTL32_Str/ &&
+ $internal_name !~ /^(?:\Q$module32\E|wine)_(?:\Q$external_name32\E|\d+)$/))
+ {
+ $output->write("no prototype\n");
}
}
}
}
}
+
+ $output->prefix("");
};
my $config = 0;
my $conditional = 0;
my $found_include = sub {
local $_ = shift;
- if(/^\"config\.h\"/) {
+ if(/^\"(?:config\.h|wine\/port\.h)\"/) {
$config++;
}
};
my $found_conditional = sub {
- if($file_type ne "application") {
- local $_ = shift;
- 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");
- }
- }
- }
+ local $_ = shift;
+
+ $nativeapi->found_conditional($_);
+
+ if($options->config) {
+ 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");
+ }
+ }
+ }
};
+
+ my $create_type = sub {
+ return 'type'->new;
+ };
+
+ my $found_type = sub {
+ my $type = shift;
+ };
+
my $preprocessor = 'preprocessor'->new($found_include, $found_conditional);
my $found_preprocessor = sub {
my $directive = shift;
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($header !~ /^ctype.h$/) {
+ if(defined($header)) {
+ my $include;
+ if(-e "$wine_dir/include/$header") {
+ $include = "include/$header";
+ } elsif(-e "$file_dir/$header") {
+ $include = "$file_dir/$header";
+ } elsif(-e "$file_dir/../$header") {
+ if($file_dir =~ m%^(.*?)/[^/]+$%) {
+ $include = "$1/$header";
+ } else {
+ $include = "$header";
+ }
+ } elsif($header =~ /^(?:kernel_private\.h)$/) { # FIXME: Kludge
+ $include = "dlls/kernel/$header";
+ } elsif($header =~ /^(?:gdi_private\.h)$/) { # FIXME: Kludge
+ $include = "dlls/gdi/$header";
+ } elsif($header =~ /^(?:ntdll_misc\.h)$/) { # FIXME: Kludge
+ $include = "dlls/ntdll/$header";
+ } elsif($header =~ /^(?:controls\.h|message\.h)$/) { # FIXME: Kludge
+ $include = "dlls/user/$header";
+ } elsif($header =~ /^(?:ts_xlib\.h|winproc\.h|x11drv\.h|x11font\.h)$/) { # FIXME: Kludge
+ $include = "dlls/x11drv/$header";
+ } elsif($check_local && $header ne "config.h") {
+ $output->write("$file: #include \"$header\": file not found\n");
+ }
+
+ if(defined($include)) {
+ $includes{$include}++;
+ foreach my $include (keys(%{$include2info{$include}{includes}})) {
+ $includes{$include}++;
+ }
+ }
+ }
+
+ if($check_protection && $header) {
+ if((-e "$wine_dir/include/$header" || -e "$wine_dir/$file_dir/$header")) {
+ if($header !~ /^(oleauto\.h|win(?:base|def|error|gdi|nls|nt|user)\.h)$/ &&
+ $file_dir !~ /tests$/)
+ {
$output->write("$file: #include \<$header\> is a local include\n");
}
}
my $macro = uc($header);
$macro =~ y/\.\//__/;
$macro = "HAVE_" . $macro;
-
- if($nativeapi->is_conditional_header($header)) {
+
+ if($nativeapi->is_conditional_header($header)) {
if(!$preprocessor->is_def($macro)) {
if($macro =~ /^HAVE_X11/) {
- if(!$preprocessor->is_undef("X_DISPLAY_MISSING")) {
- $output->write("$file: #$directive $argument: is a conditional include, " .
- "but is not protected\n");
- }
+ # Do nothing X Windows is handled differently
} elsif($macro =~ /^HAVE_(.*?)_H$/) {
- if($header ne "alloca.h" && !$preprocessor->is_def("STATFS_DEFINED_BY_$1")) {
- $output->write("$file: #$directive $argument: is a conditional include, " .
+ my $name = $1;
+ if($header !~ /^alloca\.h$/ &&
+ $file_dir !~ /tests$/ &&
+ !$preprocessor->is_def("STATFS_DEFINED_BY_$name"))
+ {
+ $output->write("$file: #$directive $argument: is a conditional include, " .
"but is not protected\n");
}
}
}
}
- 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") {
+ 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 =~ /^(?:kernel_private\.h)$/) { # FIXME: Kludge
+ $include2info{"dlls/kernel/$header"}{used}++;
+ foreach my $name (keys(%{$include2info{"dlls/kernel/$header"}{includes}})) {
+ $include2info{$name}{used}++;
+ }
+ } elsif($header =~ /^(?:gdi_private\.h)$/) { # FIXME: Kludge
+ $include2info{"dlls/gdi/$header"}{used}++;
+ foreach my $name (keys(%{$include2info{"dlls/gdi/$header"}{includes}})) {
+ $include2info{$name}{used}++;
+ }
+ } elsif($header =~ /^(?:ntdll_misc\.h)$/) { # FIXME: Kludge
+ $include2info{"dlls/ntdll/$header"}{used}++;
+ foreach my $name (keys(%{$include2info{"dlls/ntdll/$header"}{includes}})) {
+ $include2info{$name}{used}++;
+ }
+ } elsif($header =~ /^(?:controls\.h|message\.h)$/) { # FIXME: Kludge
+ $include2info{"dlls/user/$header"}{used}++;
+ foreach my $name (keys(%{$include2info{"dlls/user/$header"}{includes}})) {
+ $include2info{$name}{used}++;
+ }
+ } elsif($header =~ /^(?:ts_xlib\.h|winproc\.h|x11drv\.h|x11font\.h)$/) { # FIXME: Kludge
+ $include2info{"dlls/x11drv/$header"}{used}++;
+ foreach my $name (keys(%{$include2info{"dlls/x11drv/$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 {
+ } elsif ($header ne "config.h") {
$output->write("$file: #include \"$header\" is not a local include\n");
}
}
}
}
};
-
- winapi_parser::parse_c_file $options, $output, $file, $found_function, $found_preprocessor;
-
- if($options->config_unnessary) {
+
+ &winapi_parser::parse_c_file($file, {
+ c_comment_found => $found_c_comment,
+ cplusplus_comment_found => $found_cplusplus_comment,
+ function_create => $create_function,
+ function_found => $found_function,
+ type_create => $create_type,
+ type_found => $found_type,
+ preprocessor_found => $found_preprocessor
+ });
+
+ if($options->config_unnecessary) {
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");
}
}
- winapi_local::check_file $options, $output, $file, \%functions;
+ &winapi_local::check_file($file, \%functions);
}
-$output->hide_progress;
-
if($options->global) {
- if($options->documentation_width) {
- foreach my $width (sort(keys(%comment_width))) {
- my $count = $comment_width{$width};
- $output->write("*.c: $count functions have comments of width $width\n");
- }
- }
-
- if($options->stubs) {
- if($options->win16) {
- my %module_stub_count16;
- my %module_total_count16;
+ &winapi_global::check_modules(\%complete_module, \%module2functions);
- foreach my $name ($win16api->all_functions,$win16api->all_functions_stub) {
- foreach my $module (split(/ \& /, $win16api->function_module($name))) {
- if($win16api->function_stub($name)) {
- $module_stub_count16{$module}++;
- }
- $module_total_count16{$module}++;
- }
- }
-
- foreach my $module (sort(keys(%module_pseudo_stub_count16))) {
- if($options->report_module($module)) {
- my $real_stubs = $module_stub_count16{$module};
- my $pseudo_stubs = $module_pseudo_stub_count16{$module};
-
- if(!defined($real_stubs)) { $real_stubs = 0; }
- if(!defined($pseudo_stubs)) { $pseudo_stubs = 0; }
-
- my $stubs = $real_stubs + $pseudo_stubs;
- my $total = $module_total_count16{$module};
-
- if($stubs) {
- $output->write("*.c: $module: $stubs of $total functions are stubs ($real_stubs real, $pseudo_stubs pseudo)\n");
- }
- }
- }
- }
-
- if($options->win32) {
- my %module_stub_count32;
- my %module_total_count32;
-
- foreach my $name ($win32api->all_functions,$win32api->all_functions_stub) {
- foreach my $module (split(/ \& /, $win32api->function_module($name))) {
- if($win32api->function_stub($name)) {
- $module_stub_count32{$module}++;
- }
- $module_total_count32{$module}++;
- }
- }
-
- foreach my $module (sort(keys(%module_pseudo_stub_count32))) {
- if($options->report_module($module)) {
- my $real_stubs = $module_stub_count32{$module};
- my $pseudo_stubs = $module_pseudo_stub_count32{$module};
-
- if(!defined($real_stubs)) { $real_stubs = 0; }
- if(!defined($pseudo_stubs)) { $pseudo_stubs = 0; }
-
- my $stubs = $real_stubs + $pseudo_stubs;
- my $total = $module_total_count32{$module};
-
- if($stubs) {
- $output->write("*.c: $module: $stubs of $total functions are stubs ($real_stubs real, $pseudo_stubs pseudo)\n");
- }
- }
- }
- }
- }
-
- foreach my $name (sort(keys(%includes))) {
- if(!$includes{$name}{used}) {
- if($options->include) {
- $output->write("*.c: $name: include file is never used\n");
- }
- }
+ if($all_modules) {
+ &winapi_global::check_all_modules(\%include2info);
}
-
- winapi_global::check $options, $output, $win16api, $nativeapi if $options->win16;
- winapi_global::check $options, $output, $win32api, $nativeapi if $options->win32;
}