diff --git a/tools/winapi_check/win16/msvideo.api b/tools/winapi_check/win16/msvideo.api index deb26e1d4bf..9aa96e27bed 100644 --- a/tools/winapi_check/win16/msvideo.api +++ b/tools/winapi_check/win16/msvideo.api @@ -10,6 +10,10 @@ LPBITMAPINFOHEADER LPDWORD LPVOID +%str + +LPSTR + %word BOOL16 diff --git a/tools/winapi_check/win16/user.api b/tools/winapi_check/win16/user.api index 289fdb00cce..48c69953bb9 100644 --- a/tools/winapi_check/win16/user.api +++ b/tools/winapi_check/win16/user.api @@ -23,12 +23,14 @@ CONTEXT86 * CURSORICONINFO * DRAWSTATEPROC16 DWORD * +HANDLE * HHOOK * INT16 * LPBYTE LPCOMSTAT16 LPCVOID LPDCB16 +LPDEVMODEA LPDRIVERINFOSTRUCT16 LPDWORD LPICONINFO16 diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check index 77aacc07b8e..9e963f3f8ea 100755 --- a/tools/winapi_check/winapi_check +++ b/tools/winapi_check/winapi_check @@ -36,6 +36,7 @@ BEGIN { require "output.pm"; require "preprocessor.pm"; require "winapi.pm"; + require "winapi_documentation.pm"; require "winapi_function.pm"; require "winapi_local.pm"; require "winapi_global.pm"; @@ -47,6 +48,7 @@ BEGIN { import output; import preprocessor; import winapi; + import winapi_documentation; import winapi_function; import winapi_local; import winapi_global; @@ -245,9 +247,6 @@ if($options->headers) { } } -my %comment_width; -my %comment_indent; -my %comment_spacing; my %module_pseudo_stub_count16; my %module_pseudo_stub_count32; @@ -322,6 +321,7 @@ foreach my $file ($options->c_files) { $function->internal_name($internal_name); $function->argument_types([@argument_types]); $function->argument_names([@argument_names]); + $function->argument_documentations([@argument_documentations]); $function->statements($statements); $function->module16($module16); $function->module32($module32); @@ -443,163 +443,7 @@ foreach my $file ($options->c_files) { (defined($module16) || defined($module32)) && $linkage ne "extern" && $statements) { - my $external_name; - my $name1; - my $name2; - - if(defined($module16) && !defined($module32)) { - my @uc_modules16 = split(/\s*\&\s*/, uc($module16)); - push @uc_modules16, "WIN16"; - - $name1 = $internal_name; - foreach my $uc_module16 (@uc_modules16) { - if($name1 =~ s/^$uc_module16\_//) { last; } - } - - $name2 = $name1; - $name2 =~ s/(?:_)?16$//; - $name2 =~ s/16_fn/16_/; - - $external_name = $external_name16; - } elsif(!defined($module16) && defined($module32)) { - my @uc_modules32 = split(/\s*\&\s*/, uc($module32)); - push @uc_modules32, "wine"; - - foreach my $uc_module32 (@uc_modules32) { - if($uc_module32 =~ /^WS2_32$/) { - push @uc_modules32, "WSOCK32"; - } - } - - $name1 = $internal_name; - foreach my $uc_module32 (@uc_modules32) { - if($name1 =~ s/^$uc_module32\_//) { last; } - } - - $name2 = $name1; - $name2 =~ s/AW$//; - - $external_name = $external_name32; - } else { - my @uc_modules = split(/\s*\&\s*/, uc($module16)); - push @uc_modules, split(/\s*\&\s*/, uc($module32)); - - $name1 = $internal_name; - foreach my $uc_module (@uc_modules) { - if($name1 =~ s/^$uc_module\_//) { last; } - } - - $name2 = $name1; - $external_name = $external_name32; - } - - if(!defined($external_name)) { - $external_name = $internal_name; - } - - if($options->documentation_pedantic) { - my $n = 0; - if((++$n && defined($module16) && defined($external_name16) && - $external_name16 ne "@" && $documentation !~ /\b\Q$external_name16\E\b/) || - (++$n && defined($module16) && defined($external_name16) && - $external_name16 eq "@" && $documentation !~ /\@/) || - (++$n && defined($module32) && defined($external_name32) && - $external_name32 ne "@" && $documentation !~ /\b\Q$external_name32\E\b/) || - (++$n && defined($module32) && defined($external_name32) && - $external_name32 eq "@" && $documentation !~ /\@/)) - { - my $external_name = ($external_name16, $external_name32)[($n-1)/2]; - $output->write("documentation: wrong or missing name ($external_name) \\\n$documentation\n"); - } - } else { - if($documentation !~ /\b(?:\Q$external_name\E|$internal_name|$name1|$name2)\b/) { - $output->write("documentation: wrong or missing name \\\n$documentation\n"); - } - } - - if($options->documentation_ordinal) { - if(defined($module16)) { - my $ordinal16 = $win16api->function_ordinal($internal_name); - - if(!defined($ordinal16)) { - $output->write("function have no ordinal\n"); - } else { - my @uc_modules16 = split(/\s*\&\s*/, uc($module16)); - foreach my $uc_module16 (@uc_modules16) { - if($documentation !~ /\b$uc_module16\.\Q$ordinal16\E/) { - $output->write("documentation: wrong or missing ordinal " . - "expected (\U$module16\E.$ordinal16)\\\n$documentation\n"); - } - } - } - } - if(defined($module32)) { - my $ordinal32 = $win32api->function_ordinal($internal_name); - - if(!defined($ordinal32)) { - $output->write("function have no ordinal\n"); - } else { - my @uc_modules32 = split(/\s*\&\s*/, uc($module32)); - foreach my $uc_module32 (@uc_modules32) { - if($documentation !~ /\b$uc_module32\.\Q$ordinal32\E/) { - $output->write("documentation: wrong or missing ordinal " . - "expected (\U$module32\E.$ordinal32) \\\n$documentation\n"); - } - } - } - } - } - - if($options->documentation_pedantic) { - if($documentation !~ /^ \*\t\t(?:\@|\w+)(?: \(\w+\.(?:\@|\d+)\))+/m) { - $output->write("documentation: pedantic check failed \\\n$documentation\n"); - } - } - - if($options->documentation_comment_indent) { - if($documentation =~ /^ \*(\s*)\w+(\s*)([\(\[])\s*\w+\.\s*(?:\@|\d+)\s*([\)\]])/m) { - my $indent = $1; - my $spacing = $2; - my $left = $3; - my $right = $4; - - $indent =~ s/\t/ /g; - $indent = length($indent); - - $spacing =~ s/\t/ /g; - $spacing = length($spacing); - - $comment_indent{$indent}++; - if($indent >= 20) { - $output->write("documentation: comment indent is $indent\n"); - } - - $comment_spacing{$spacing}++; - } - } - - if($options->documentation_comment_width) { - if($documentation =~ /(^\/\*\*+)/) { - my $width = length($1); - - $comment_width{$width}++; - if($width <= 65 || $width >= 81) { - $output->write("comment is $width columns wide\n"); - } - } - } - - if($options->documentation_arguments) { - my $n = 0; - for my $argument_documentation (@argument_documentations) { - $n++; - if($argument_documentation ne "") { - if($argument_documentation !~ /^\/\*\s+\[(?:in|out|in\/out|\?\?\?)\].*?\*\/$/s) { - $output->write("argument $n documentation: \\\n$argument_documentation\n"); - } - } - } - } + winapi_documentation::check_documentation $options, $output, $win16api, $win32api, $function; } $output->prefix(""); } @@ -731,19 +575,7 @@ foreach my $file ($options->c_files) { $output->hide_progress; if($options->global) { - if($options->documentation_comment_indent) { - foreach my $indent (sort(keys(%comment_indent))) { - my $count = $comment_indent{$indent}; - $output->write("*.c: $count functions have comment that is indented $indent\n"); - } - } - - if($options->documentation_comment_width) { - foreach my $width (sort(keys(%comment_width))) { - my $count = $comment_width{$width}; - $output->write("*.c: $count functions have comments of width $width\n"); - } - } + winapi_documentation::report_documentation $options, $output; if($options->stubs) { if($options->win16) { diff --git a/tools/winapi_check/winapi_documentation.pm b/tools/winapi_check/winapi_documentation.pm new file mode 100644 index 00000000000..435f756de63 --- /dev/null +++ b/tools/winapi_check/winapi_documentation.pm @@ -0,0 +1,202 @@ +package winapi_documentation; + +use strict; + +my %comment_width; +my %comment_indent; +my %comment_spacing; + +sub check_documentation { + my $options = shift; + my $output = shift; + my $win16api = shift; + my $win32api = shift; + my $function = shift; + + my $module16 = $function->module16; + my $module32 = $function->module32; + my $external_name16 = $function->external_name16; + my $external_name32 = $function->external_name32; + my $internal_name = $function->internal_name; + my $documentation = $function->documentation; + my @argument_documentations = @{$function->argument_documentations}; + + my $external_name; + my $name1; + my $name2; + + if(defined($module16) && !defined($module32)) { + my @uc_modules16 = split(/\s*\&\s*/, uc($module16)); + push @uc_modules16, "WIN16"; + + $name1 = $internal_name; + foreach my $uc_module16 (@uc_modules16) { + if($name1 =~ s/^$uc_module16\_//) { last; } + } + + $name2 = $name1; + $name2 =~ s/(?:_)?16$//; + $name2 =~ s/16_fn/16_/; + + $external_name = $external_name16; + } elsif(!defined($module16) && defined($module32)) { + my @uc_modules32 = split(/\s*\&\s*/, uc($module32)); + push @uc_modules32, "wine"; + + foreach my $uc_module32 (@uc_modules32) { + if($uc_module32 =~ /^WS2_32$/) { + push @uc_modules32, "WSOCK32"; + } + } + + $name1 = $internal_name; + foreach my $uc_module32 (@uc_modules32) { + if($name1 =~ s/^$uc_module32\_//) { last; } + } + + $name2 = $name1; + $name2 =~ s/AW$//; + + $external_name = $external_name32; + } else { + my @uc_modules = split(/\s*\&\s*/, uc($module16)); + push @uc_modules, split(/\s*\&\s*/, uc($module32)); + + $name1 = $internal_name; + foreach my $uc_module (@uc_modules) { + if($name1 =~ s/^$uc_module\_//) { last; } + } + + $name2 = $name1; + $external_name = $external_name32; + } + + if(!defined($external_name)) { + $external_name = $internal_name; + } + + if($options->documentation_pedantic) { + my $n = 0; + if((++$n && defined($module16) && defined($external_name16) && + $external_name16 ne "@" && $documentation !~ /\b\Q$external_name16\E\b/) || + (++$n && defined($module16) && defined($external_name16) && + $external_name16 eq "@" && $documentation !~ /\@/) || + (++$n && defined($module32) && defined($external_name32) && + $external_name32 ne "@" && $documentation !~ /\b\Q$external_name32\E\b/) || + (++$n && defined($module32) && defined($external_name32) && + $external_name32 eq "@" && $documentation !~ /\@/)) + { + my $external_name = ($external_name16, $external_name32)[($n-1)/2]; + $output->write("documentation: wrong or missing name ($external_name) \\\n$documentation\n"); + } + } else { + if($documentation !~ /\b(?:\Q$external_name\E|$internal_name|$name1|$name2)\b/) { + $output->write("documentation: wrong or missing name \\\n$documentation\n"); + } + } + + if($options->documentation_ordinal) { + if(defined($module16)) { + my $ordinal16 = $win16api->function_ordinal($internal_name); + + if(!defined($ordinal16)) { + $output->write("function have no ordinal\n"); + } else { + my @uc_modules16 = split(/\s*\&\s*/, uc($module16)); + foreach my $uc_module16 (@uc_modules16) { + if($documentation !~ /\b$uc_module16\.\Q$ordinal16\E/) { + $output->write("documentation: wrong or missing ordinal " . + "expected (\U$module16\E.$ordinal16)\\\n$documentation\n"); + } + } + } + } + if(defined($module32)) { + my $ordinal32 = $win32api->function_ordinal($internal_name); + + if(!defined($ordinal32)) { + $output->write("function have no ordinal\n"); + } else { + my @uc_modules32 = split(/\s*\&\s*/, uc($module32)); + foreach my $uc_module32 (@uc_modules32) { + if($documentation !~ /\b$uc_module32\.\Q$ordinal32\E/) { + $output->write("documentation: wrong or missing ordinal " . + "expected (\U$module32\E.$ordinal32) \\\n$documentation\n"); + } + } + } + } + } + + if($options->documentation_pedantic) { + if($documentation !~ /^ \*\s+(?:\@|\w+)(?:\s+\(\w+\.(?:\@|\d+)\))+/m) { + $output->write("documentation: pedantic check failed \\\n$documentation\n"); + } + } + + if($options->documentation_comment_indent) { + if($documentation =~ /^ \*(\s*)\w+(\s*)([\(\[])\s*\w+\.\s*(?:\@|\d+)\s*([\)\]])/m) { + my $indent = $1; + my $spacing = $2; + my $left = $3; + my $right = $4; + + $indent =~ s/\t/ /g; + $indent = length($indent); + + $spacing =~ s/\t/ /g; + $spacing = length($spacing); + + $comment_indent{$indent}++; + if($indent >= 20) { + $output->write("documentation: comment indent is $indent\n"); + } + + $comment_spacing{$spacing}++; + } + } + + if($options->documentation_comment_width) { + if($documentation =~ /(^\/\*\*+)/) { + my $width = length($1); + + $comment_width{$width}++; + if($width <= 65 || $width >= 81) { + $output->write("comment is $width columns wide\n"); + } + } + } + + if($options->documentation_arguments) { + my $n = 0; + for my $argument_documentation (@argument_documentations) { + $n++; + if($argument_documentation ne "") { + if($argument_documentation !~ /^\/\*\s+\[(?:in|out|in\/out|\?\?\?)\].*?\*\/$/s) { + $output->write("argument $n documentation: \\\n$argument_documentation\n"); + } + } + } + } +} + +sub report_documentation { + my $options = shift; + my $output = shift; + + if($options->documentation_comment_indent) { + foreach my $indent (sort(keys(%comment_indent))) { + my $count = $comment_indent{$indent}; + $output->write("*.c: $count functions have comment that is indented $indent\n"); + } + } + + if($options->documentation_comment_width) { + foreach my $width (sort(keys(%comment_width))) { + my $count = $comment_width{$width}; + $output->write("*.c: $count functions have comments of width $width\n"); + } + } +} + +1; diff --git a/tools/winapi_check/winapi_function.pm b/tools/winapi_check/winapi_function.pm index 50a52b5131e..e6b18790382 100644 --- a/tools/winapi_check/winapi_function.pm +++ b/tools/winapi_check/winapi_function.pm @@ -121,6 +121,17 @@ sub argument_names { return $$argument_names; } +sub argument_documentations { + my $self = shift; + my $argument_documentations = \${$self->{ARGUMENT_DOCUMENTATIONS}}; + + local $_ = shift; + + if(defined($_)) { $$argument_documentations = $_; } + + return $$argument_documentations; +} + sub module16 { my $self = shift; my $module16 = \${$self->{MODULE16}}; diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm index 8c4113c1d08..6404a6c205c 100644 --- a/tools/winapi_check/winapi_local.pm +++ b/tools/winapi_check/winapi_local.pm @@ -60,12 +60,16 @@ sub check_function { $implemented_calling_convention = "cdecl"; } elsif($calling_convention =~ /^VFWAPIV|WINAPIV$/) { $implemented_calling_convention = "varargs"; - } elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI|CALLBACK$/) { + } elsif($calling_convention =~ /^__stdcall|VFWAPI|WINAPI|CALLBACK$/) { if($implemented_return_kind =~ /^s_word|word|void$/) { $implemented_calling_convention = "pascal16"; } else { $implemented_calling_convention = "pascal"; } + } elsif($calling_convention =~ /^__asm$/) { + $implemented_calling_convention = "asm"; + } else { + $implemented_calling_convention = "cdecl"; } } elsif($winapi->name eq "win32") { if($calling_convention =~ /^__cdecl$/) { @@ -78,6 +82,8 @@ sub check_function { } else { $implemented_calling_convention = "stdcall"; } + } elsif($calling_convention =~ /^__asm$/) { + $implemented_calling_convention = "asm"; } else { $implemented_calling_convention = "cdecl"; } @@ -95,7 +101,8 @@ sub check_function { (($winapi->name eq "win16" && $implemented_calling_convention =~ /^pascal/)))) { # correct - } elsif($implemented_calling_convention ne $declared_calling_convention && + } elsif($implemented_calling_convention ne $declared_calling_convention && + $implemented_calling_convention ne "asm" && !($declared_calling_convention =~ /^pascal/ && $forbidden_return_type) && !($implemented_calling_convention =~ /^cdecl|varargs$/ && $declared_calling_convention =~ /^cdecl|varargs$/)) { @@ -182,7 +189,10 @@ sub check_function { } } } - if($#argument_kinds != $#declared_argument_kinds) { + + if($#argument_kinds != $#declared_argument_kinds && + $implemented_calling_convention ne "asm") + { if($options->argument_count) { $output->write("argument count differs: " . ($#argument_types + 1) . " != " . diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm index c45b21de973..9eb882a1c48 100644 --- a/tools/winapi_check/winapi_parser.pm +++ b/tools/winapi_check/winapi_parser.pm @@ -303,6 +303,11 @@ sub parse_c_file { if($level == 0) { &$function_end; } + } elsif(/__ASM_GLOBAL_FUNC\(\s*(.*?)\s*,/s) { + $_ = $'; $again = 1; + my @arguments = (); + &$function_begin($documentation, "", "void", "__asm", $1, \@arguments); + &$function_end; } elsif(/DC_(GET_X_Y|GET_VAL_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; my @arguments = ("HDC16");