diff --git a/tools/winapi_check/nativeapi.pm b/tools/winapi_check/nativeapi.pm index 136689d4e3a..b59da36f009 100644 --- a/tools/winapi_check/nativeapi.pm +++ b/tools/winapi_check/nativeapi.pm @@ -9,17 +9,59 @@ sub new { bless ($self, $class); my $functions = \%{$self->{FUNCTIONS}}; + my $conditionals = \%{$self->{CONDITIONALS}}; + my $conditional_headers = \%{$self->{CONDITIONAL_HEADERS}}; - my $file = shift; + my $api_file = shift; + my $configure_in_file = shift; + my $config_h_in_file = shift; - open(IN, "< $file"); + open(IN, "< $api_file"); $/ = "\n"; while() { s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line s/^(.*?)\s*#.*$/$1/; # remove comments /^$/ && next; # skip empty lines - $$functions{$_} = 1; + $$functions{$_}++; + } + close(IN); + + my $again = 0; + open(IN, "< $configure_in_file"); + local $/ = "\n"; + while($again || (defined($_ = ))) { + $again = 0; + chomp; + if(/(.*)\\$/) { + my $line = ; + if(defined($line)) { + $_ = $1 . " " . $line; + $again = 1; + next; + } + } + # remove leading and trailing whitespace + s/^\s*(.*?)\s*$/$1/; + + if(/^AC_CHECK_HEADERS\(\s*(.*?)\)\s*$/) { + my @arguments = split(/,/,$1); + foreach my $header (split(/\s+/, $arguments[0])) { + $$conditional_headers{$header}++; + } + } elsif(/^AC_FUNC_ALLOCA/) { + $$conditional_headers{"alloca.h"}++; + } + + } + close(IN); + + open(IN, "< $config_h_in_file"); + local $/ = "\n"; + while() { + if(/^\#undef (\S+)$/) { + $$conditionals{$1}++; + } } close(IN); @@ -35,4 +77,22 @@ sub is_function { return $$functions{$name}; } +sub is_conditional { + my $self = shift; + my $conditionals = \%{$self->{CONDITIONALS}}; + + my $name = shift; + + return $$conditionals{$name}; +} + +sub is_conditional_header { + my $self = shift; + my $conditional_headers = \%{$self->{CONDITIONAL_HEADERS}}; + + my $name = shift; + + return $$conditional_headers{$name}; +} + 1; diff --git a/tools/winapi_check/output.pm b/tools/winapi_check/output.pm new file mode 100644 index 00000000000..0c0fb328e52 --- /dev/null +++ b/tools/winapi_check/output.pm @@ -0,0 +1,91 @@ +package output; + +use strict; + +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}}; + + $$progress = ""; + $$last_progress = ""; + + return $self; +} + + +sub show_progress { + my $self = shift; + my $progress = \${$self->{PROGRESS}}; + my $last_progress = \${$self->{LAST_PROGRESS}}; + + if($$progress) { + print STDERR $$progress; + $$last_progress = $$progress; + } +} + +sub hide_progress { + my $self = shift; + my $progress = \${$self->{PROGRESS}}; + my $last_progress = \${$self->{LAST_PROGRESS}}; + + if($$last_progress) { + 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 = ""; + for (1..length($$last_progress)) { + $prefix .= ""; + } + + my $suffix = ""; + 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 write { + my $self = shift; + my $last_progress = \${$self->{LAST_PROGRESS}}; + + my $message = shift; + + $self->hide_progress; + print STDERR $message; + $self->show_progress; +} + +1; diff --git a/tools/winapi_check/preprocessor.pm b/tools/winapi_check/preprocessor.pm new file mode 100644 index 00000000000..dd9fbd43b7b --- /dev/null +++ b/tools/winapi_check/preprocessor.pm @@ -0,0 +1,175 @@ +package preprocessor; + +use strict; + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = {}; + bless ($self, $class); + + my $state = \%{$self->{STATE}}; + my $stack = \@{$self->{STACK}}; + my $include_found = \${$self->{INCLUDE_FOUND}}; + my $conditional_found = \${$self->{CONDITIONAL_FOUND}}; + + $$include_found = shift; + $$conditional_found = shift; + + return $self; +} + +sub include { + my $self = shift; + my $include_found = \${$self->{INCLUDE_FOUND}}; + + my $argument = shift; + + &$$include_found($argument); +} + +sub define { + my $self = shift; + my $state = \%{$self->{STATE}}; + my $conditional_found = \${$self->{CONDITIONAL_FOUND}}; + + my $name = shift; + + $$state{$name} = "def"; + + &$$conditional_found($name); +} + +sub undefine { + my $self = shift; + my $state = \%{$self->{STATE}}; + my $conditional_found = \${$self->{CONDITIONAL_FOUND}}; + + my $name = shift; + + $$state{$name} = "undef"; + + &$$conditional_found($name); +} + +sub begin_if { + my $self = shift; + my $state = \%{$self->{STATE}}; + my $stack = \@{$self->{STACK}}; + + my $directive = shift; + local $_ = shift; + + while(!/^$/) { + if(/^0\s*\&\&/) { + $_ = "0"; + } elsif(/^1\s*\|\|/) { + $_ = "1"; + } + + if(/^(!)?defined\s*\(\s*(.+?)\s*\)\s*((\&\&|\|\|)\s*)?/){ + $_ = $'; + if(defined($1) && $1 eq "!") { + $self->undefine($2); + push @$stack, $2; + } else { + $self->define($2); + push @$stack, $2; + } + } elsif(/^(\w+)\s*(<|<=|==|!=|>=|>)\s*(\w+)\s*((\&\&|\|\|)\s*)?/) { + $_ = $'; + } elsif(/^(\w+)\s*$/) { + $_ = $'; + } elsif(/^\(|\)/) { + $_ = $'; + } else { + print "*** Can't parse '#$directive $_' ***\n"; + $_ = ""; + } + } +} + +sub else_if { + my $self = shift; + my $state = \%{$self->{STATE}}; + my $stack = \@{$self->{STACK}}; + + my $argument = shift; + + $self->end_if; + + if(defined($argument)) { + $self->begin_if("elif", $argument); + } +} + +sub end_if { + my $self = shift; + my $state = \%{$self->{STATE}}; + my $stack = \@{$self->{STACK}}; + + my $macro = pop @$stack; + delete $$state{$macro} if defined($macro); +} + +sub directive { + my $self = shift; + my $state = \%{$self->{STATE}}; + my $stack = \@{$self->{STACK}}; + + my $directive = shift; + my $argument = shift; + + local $_ = $directive; + if(/^if$/) { + $self->begin_if("if",$argument); + } elsif(/^ifdef$/) { + $self->begin_if("if", "defined($argument)"); + } elsif(/^ifndef$/) { + $self->begin_if("if", "!defined($argument)"); + push @$stack, $argument; + } elsif(/^elif$/) { + $self->else_if($argument); + } elsif(/^else$/) { + $self->else_if; + } elsif(/^endif$/) { + $self->end_if; + } elsif(/^include/) { + $self->include($argument); + } +} + +sub is_def { + my $self = shift; + my $state = \%{$self->{STATE}}; + + my $name = shift; + + my $status = $$state{$name}; + + return defined($status) && $status eq "def"; +} + +sub is_undef { + my $self = shift; + my $state = \%{$self->{STATE}}; + + my $name = shift; + + my $status = $$state{$name}; + + return defined($status) && $status eq "undef"; +} + +sub is_unknown { + my $self = shift; + my $state = \%{$self->{STATE}}; + + my $name = shift; + + my $status = $$state{$name}; + + return !defined($status); +} + +1; diff --git a/tools/winapi_check/win16/display.api b/tools/winapi_check/win16/display.api new file mode 100644 index 00000000000..e184c7e71b9 --- /dev/null +++ b/tools/winapi_check/win16/display.api @@ -0,0 +1,3 @@ +%word + +HDC16 diff --git a/tools/winapi_check/win16/gdi.api b/tools/winapi_check/win16/gdi.api new file mode 100644 index 00000000000..e184c7e71b9 --- /dev/null +++ b/tools/winapi_check/win16/gdi.api @@ -0,0 +1,3 @@ +%word + +HDC16 diff --git a/tools/winapi_check/win16/olecli.api b/tools/winapi_check/win16/olecli.api new file mode 100644 index 00000000000..e184c7e71b9 --- /dev/null +++ b/tools/winapi_check/win16/olecli.api @@ -0,0 +1,3 @@ +%word + +HDC16 diff --git a/tools/winapi_check/win16/user.api b/tools/winapi_check/win16/user.api new file mode 100644 index 00000000000..e184c7e71b9 --- /dev/null +++ b/tools/winapi_check/win16/user.api @@ -0,0 +1,3 @@ +%word + +HDC16 diff --git a/tools/winapi_check/win16/wing.api b/tools/winapi_check/win16/wing.api new file mode 100644 index 00000000000..e184c7e71b9 --- /dev/null +++ b/tools/winapi_check/win16/wing.api @@ -0,0 +1,3 @@ +%word + +HDC16 diff --git a/tools/winapi_check/win16api.dat b/tools/winapi_check/win16api.dat index a9d299bcbc2..f946ee6f1b4 100644 --- a/tools/winapi_check/win16api.dat +++ b/tools/winapi_check/win16api.dat @@ -24,6 +24,7 @@ ULONG %longlong LARGE_INTEGER +ULARGE_INTEGER %ptr @@ -157,6 +158,7 @@ LPPAINTSTRUCT16 LPPALETTEENTRY LPPDEVICE LPPOINT16 +LPPRINTDLG16 LPQUEUESTRUCT16 * LPRASTERIZER_STATUS LPRECT16 @@ -290,7 +292,6 @@ HANDLE16 HBITMAP16 HBRUSH16 HCURSOR16 -HDC16 HDROP16 HDRVR16 HDWP16 @@ -330,7 +331,7 @@ WING_DITHER_TYPE WORD WPARAM16 -%unknown --forbidden +%unknown # --forbidden BOOL FARPROC diff --git a/tools/winapi_check/win32/avifil32.api b/tools/winapi_check/win32/avifil32.api new file mode 100644 index 00000000000..6558fd261db --- /dev/null +++ b/tools/winapi_check/win32/avifil32.api @@ -0,0 +1,12 @@ +%ptr + +AVICOMPRESSOPTIONS * +AVISTREAMINFOA * +AVISTREAMINFOW * +IAVIFile * +LPAVIFILEINFOA +LPAVIFILEINFOW +PAVIFILE +PAVIFILE * +PAVISTREAM +PAVISTREAM * diff --git a/tools/winapi_check/win32/comctl32.api b/tools/winapi_check/win32/comctl32.api new file mode 100644 index 00000000000..18ff86f42e2 --- /dev/null +++ b/tools/winapi_check/win32/comctl32.api @@ -0,0 +1,7 @@ +%long + +COLORREF +HBITMAP +HDC +HICON +HWND \ No newline at end of file diff --git a/tools/winapi_check/win32/comdlg32.api b/tools/winapi_check/win32/comdlg32.api new file mode 100644 index 00000000000..c2835fac519 --- /dev/null +++ b/tools/winapi_check/win32/comdlg32.api @@ -0,0 +1,3 @@ +%long + +HWND \ No newline at end of file diff --git a/tools/winapi_check/win32/gdi32.api b/tools/winapi_check/win32/gdi32.api new file mode 100644 index 00000000000..745416739e6 --- /dev/null +++ b/tools/winapi_check/win32/gdi32.api @@ -0,0 +1,22 @@ +%long + +COLORREF +HBITMAP +HBRUSH +HCOLORSPACE +HDC +HENHMETAFILE +HFONT +HGDIOBJ +HMETAFILE +HPALETTE +HPEN +HRGN +HWND + +%ptr + +BITMAP * +BITMAPINFO * +BITMAPINFOHEADER * + diff --git a/tools/winapi_check/win32/imm32.api b/tools/winapi_check/win32/imm32.api new file mode 100644 index 00000000000..3f41c3af496 --- /dev/null +++ b/tools/winapi_check/win32/imm32.api @@ -0,0 +1,4 @@ +%long + +HWND +HIMC diff --git a/tools/winapi_check/win32/mpr.api b/tools/winapi_check/win32/mpr.api new file mode 100644 index 00000000000..c2835fac519 --- /dev/null +++ b/tools/winapi_check/win32/mpr.api @@ -0,0 +1,3 @@ +%long + +HWND \ No newline at end of file diff --git a/tools/winapi_check/win32/msacm32.api b/tools/winapi_check/win32/msacm32.api new file mode 100644 index 00000000000..98fe080c9d4 --- /dev/null +++ b/tools/winapi_check/win32/msacm32.api @@ -0,0 +1,36 @@ +%long + +HACMDRIVER +HACMDRIVERID +HACMOBJ +HACMSTREAM + +%ptr + +ACMDRIVERENUMCB +ACMFILTERENUMCBA +ACMFILTERENUMCBW +ACMFILTERTAGENUMCBA +ACMFILTERTAGENUMCBW +ACMFORMATENUMCBA +ACMFORMATENUMCBW +ACMFORMATTAGENUMCBA +ACMFORMATTAGENUMCBW +PACMDRIVERDETAILSA +PACMDRIVERDETAILSW +PACMFILTERCHOOSEA +PACMFILTERCHOOSEW +PACMFILTERDETAILSA +PACMFILTERDETAILSW +PACMFILTERTAGDETAILSA +PACMFILTERTAGDETAILSW +PACMFORMATCHOOSEA +PACMFORMATCHOOSEW +PACMFORMATDETAILSA +PACMFORMATDETAILSW +PACMFORMATTAGDETAILSA +PACMFORMATTAGDETAILSW +PACMSTREAMHEADER +PHACMDRIVER +PHACMDRIVERID +PHACMSTREAM diff --git a/tools/winapi_check/win32/msvfw32.api b/tools/winapi_check/win32/msvfw32.api new file mode 100644 index 00000000000..05c8b15d900 --- /dev/null +++ b/tools/winapi_check/win32/msvfw32.api @@ -0,0 +1,7 @@ +%long + +HDC +HIC +HPALETTE +HWND + diff --git a/tools/winapi_check/win32/ole32.api b/tools/winapi_check/win32/ole32.api new file mode 100644 index 00000000000..41888d90dcb --- /dev/null +++ b/tools/winapi_check/win32/ole32.api @@ -0,0 +1,10 @@ +%long + +CLIPFORMAT +HACCEL +HMENU +HWND + +%ptr +CLIPFORMAT * + diff --git a/tools/winapi_check/win32/oleaut32.api b/tools/winapi_check/win32/oleaut32.api new file mode 100644 index 00000000000..60895c75537 --- /dev/null +++ b/tools/winapi_check/win32/oleaut32.api @@ -0,0 +1,7 @@ +%long + +HPALETTE + +%ptr + +COLORREF * diff --git a/tools/winapi_check/win32/olecli32.api b/tools/winapi_check/win32/olecli32.api new file mode 100644 index 00000000000..8c76d1c2630 --- /dev/null +++ b/tools/winapi_check/win32/olecli32.api @@ -0,0 +1,3 @@ +%long + +HDC \ No newline at end of file diff --git a/tools/winapi_check/win32/oledlg.api b/tools/winapi_check/win32/oledlg.api new file mode 100644 index 00000000000..2a948b02898 --- /dev/null +++ b/tools/winapi_check/win32/oledlg.api @@ -0,0 +1,4 @@ +%long + +HMENU +HWND diff --git a/tools/winapi_check/win32/shell32.api b/tools/winapi_check/win32/shell32.api new file mode 100644 index 00000000000..367c116a745 --- /dev/null +++ b/tools/winapi_check/win32/shell32.api @@ -0,0 +1,8 @@ +%long + +COLORREF +HBITMAP +HMENU +HICON +HWND + diff --git a/tools/winapi_check/win32/shlwapi.api b/tools/winapi_check/win32/shlwapi.api new file mode 100644 index 00000000000..c2835fac519 --- /dev/null +++ b/tools/winapi_check/win32/shlwapi.api @@ -0,0 +1,3 @@ +%long + +HWND \ No newline at end of file diff --git a/tools/winapi_check/win32/tapi32.api b/tools/winapi_check/win32/tapi32.api new file mode 100644 index 00000000000..41c08660c6d --- /dev/null +++ b/tools/winapi_check/win32/tapi32.api @@ -0,0 +1,3 @@ +%long + +HWND diff --git a/tools/winapi_check/win32/user32.api b/tools/winapi_check/win32/user32.api new file mode 100644 index 00000000000..a392bb30e32 --- /dev/null +++ b/tools/winapi_check/win32/user32.api @@ -0,0 +1,19 @@ +%long + +COLORREF +HACCEL +HBITMAP +HBRUSH +HCURSOR +HDC +HDESK +HFONT +HICON +HMENU +HMONITOR +HRGN +HWND + +%ptr + +COLORREF * diff --git a/tools/winapi_check/win32/winmm.api b/tools/winapi_check/win32/winmm.api new file mode 100644 index 00000000000..c2835fac519 --- /dev/null +++ b/tools/winapi_check/win32/winmm.api @@ -0,0 +1,3 @@ +%long + +HWND \ No newline at end of file diff --git a/tools/winapi_check/win32/winspool.api b/tools/winapi_check/win32/winspool.api new file mode 100644 index 00000000000..c2835fac519 --- /dev/null +++ b/tools/winapi_check/win32/winspool.api @@ -0,0 +1,3 @@ +%long + +HWND \ No newline at end of file diff --git a/tools/winapi_check/win32/wsock32.api b/tools/winapi_check/win32/wsock32.api new file mode 100644 index 00000000000..41c08660c6d --- /dev/null +++ b/tools/winapi_check/win32/wsock32.api @@ -0,0 +1,3 @@ +%long + +HWND diff --git a/tools/winapi_check/win32api.dat b/tools/winapi_check/win32api.dat index 88d8673d059..4d1e0faa2f6 100644 --- a/tools/winapi_check/win32api.dat +++ b/tools/winapi_check/win32api.dat @@ -13,8 +13,6 @@ BYTE CALID CALTYPE CHAR -CLIPFORMAT -COLORREF COORD DATE DIGEST_HANDLE @@ -25,44 +23,25 @@ FLOAT FOURCC FS_INFORMATION_CLASS GET_FILEEX_INFO_LEVELS -HACCEL -HACMDRIVER -HACMDRIVERID -HACMOBJ -HACMSTREAM HANDLE -HBITMAP -HBRUSH HCALL -HCOLORSPACE HCONV HCONVLIST -HCURSOR HCRYPTKEY -HDC HDDEDATA -HDESK HDROP HDRVR HDSA HDWP -HENHMETAFILE HFILE -HFONT -HGDIOBJ HGLOBAL HHOOK -HIC -HICON -HIMC HINSTANCE HKEY HKL HLINE HLINEAPP HLOCAL -HMENU -HMETAFILE HMIDIIN HMIDIOUT HMIDISTRM @@ -70,23 +49,18 @@ HMIXER HMIXEROBJ HMMIO HMODULE -HMONITOR HOLEMENU -HPALETTE -HPEN HPHONE HPHONEAPP HPROPSHEETPAGE HPROVIDER HRESULT -HRGN HRSRC HSZ HTASK HWAVEIN HWAVEOUT HWINSTA -HWND INT KEY_INFORMATION_CLASS KEY_VALUE_INFORMATION_CLASS @@ -106,7 +80,6 @@ OLECLIPFORMAT OLEOPT_RENDER OLESTATUS OLE_SERVER_USE -OUT PHANDLE PHPROVIDER PIO_APC_ROUTINE @@ -117,6 +90,7 @@ POBJDIR_INFORMATION PROCESSINFOCLASS PTIME_FIELDS PTOKEN_PRIVILEGES +REGKIND REGSAM SC_HANDLE SECTION_INHERIT @@ -150,37 +124,21 @@ time_t LARGE_INTEGER POINT +ULARGE_INTEGER %ptr ABORTPROC -ACMDRIVERENUMCB -ACMFILTERENUMCBA -ACMFILTERENUMCBW -ACMFILTERTAGENUMCBA -ACMFILTERTAGENUMCBW -ACMFORMATENUMCBA -ACMFORMATENUMCBW -ACMFORMATTAGENUMCBA -ACMFORMATTAGENUMCBW -AVICOMPRESSOPTIONS * -AVISTREAMINFOA * -AVISTREAMINFOW * -BITMAP * -BITMAPINFO * -BITMAPINFOHEADER * BOOL * BSTR * BYTE * BY_HANDLE_FILE_INFORMATION * CALINFO_ENUMPROCA CHAR * -CLIPFORMAT * CLSID * CODEPAGE_ENUMPROCA CODEPAGE_ENUMPROCW COLORADJUSTMENT * -COLORREF * CONST CONTEXT * COSERVERINFO * @@ -238,6 +196,7 @@ HMENU * HMIDIIN * HMIDIOUT * HMIDISTRM * +HMODULE * HMRU HOOKPROC HPCSTR @@ -254,6 +213,8 @@ IDropTarget * ILockBytes * IMAGEINFO * IMAGELISTDRAWPARAMS * +IMoniker * +IMoniker ** INPUT_RECORD * INT * IPersistStream * @@ -283,8 +244,6 @@ LPACCEL LPAUTHDLGSTRUCTA LPAUXCAPSA LPAUXCAPSW -LPAVIFILEINFOA -LPAVIFILEINFOW LPBC * LPBITMAPINFOHEADER LPBOOL @@ -327,6 +286,7 @@ LPCWSTR * LPDATAADVISEHOLDER * LPDATAOBJECT LPDCB +LPDCB * LPDDENUMCALLBACKA LPDDENUMCALLBACKEXA LPDDENUMCALLBACKEXW @@ -434,8 +394,10 @@ LPMIXERLINECONTROLSW LPMIXERLINEW LPMMCKINFO LPMMIOPROC +LPMMIOPROC16 LPMMTIME LPMODULEENTRY +LPMODULEINFO LPMONIKER LPMONIKER * LPMONITORINFO @@ -579,31 +541,12 @@ PACE_HEADER PACE_HEADER * PACL PACL * -PACMDRIVERDETAILSA -PACMDRIVERDETAILSW -PACMFILTERCHOOSEA -PACMFILTERCHOOSEW -PACMFILTERDETAILSA -PACMFILTERDETAILSW -PACMFILTERTAGDETAILSA -PACMFILTERTAGDETAILSW -PACMFORMATCHOOSEA -PACMFORMATCHOOSEW -PACMFORMATDETAILSA -PACMFORMATDETAILSW -PACMFORMATTAGDETAILSA -PACMFORMATTAGDETAILSW -PACMSTREAMHEADER PAINTSTRUCT * PALETTEENTRY * PANSI_STRING PAPCFUNC PAPI_VERSION PAPPBARDATA -PAVIFILE -PAVIFILE * -PAVISTREAM -PAVISTREAM * PBOOLEAN PBYTE PCHAR @@ -623,9 +566,6 @@ PFUNCTION_TABLE_ACCESS_ROUTINE PGENERIC_MAPPING PGETFRAME PGET_MODULE_BASE_ROUTINE -PHACMDRIVER -PHACMDRIVERID -PHACMSTREAM PHONECALLBACK PIMAGEHLP_MODULE PIMAGEHLP_STATUS_ROUTINE @@ -646,7 +586,9 @@ POBJECT_ATTRIBUTES POINT * PPOLYTEXTA PPOLYTEXTW +PPSAPI_WS_WATCH_INFORMATION PPRIVILEGE_SET +PPROCESS_MEMORY_COUNTERS PREAD_PROCESS_MEMORY_ROUTINE PRTL_HEAP_DEFINITION PROPENUMPROCA diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm index dfb3e6d87e9..95af6ff4ce8 100644 --- a/tools/winapi_check/winapi.pm +++ b/tools/winapi_check/winapi.pm @@ -8,18 +8,48 @@ sub new { my $self = {}; bless ($self, $class); + my $output = \${$self->{OUTPUT}}; + my $name = \${$self->{NAME}}; + + $$output = shift; + $$name = shift; + my $file = shift; + my $path = shift; + + $file =~ s/^.\/(.*)$/$1/; + $self->parse_api_file($file); + + my @files = map { + s/^.\/(.*)$/$1/; + $_; + } split(/\n/, `find $path -name \\*.api`); + + foreach my $file (@files) { + my $module = $file; + $module =~ s/.*?\/([^\/]*?)\.api$/$1/; + $self->parse_api_file($file,$module); + } + + return $self; +} + +sub parse_api_file { + my $self = shift; + my $output = \${$self->{OUTPUT}}; my $allowed_kind = \%{$self->{ALLOWED_KIND}}; my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}}; + my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}}; my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; - $self->{NAME} = shift; my $file = shift; + my $module = shift; - my @modules; my $kind; my $forbidden = 0; + $$output->progress("$file"); + open(IN, "< $file") || die "$file: $!\n"; $/ = "\n"; while() { @@ -29,34 +59,41 @@ sub new { if(s/^%(\S+)\s*//) { $kind = $1; - @modules = (); $forbidden = 0; $$allowed_kind{$kind} = 1; - if(/^--module=(\S*)/) { - @modules = split(/,/, $1); - } elsif(/^--forbidden/) { + if(/^--forbidden/) { $forbidden = 1; } } elsif(defined($kind)) { my $type = $_; if(!$forbidden) { - for my $module (@modules) { - $$allowed_modules_limited{$type} = 1; - $$allowed_modules{$type}{$module} = 1; + if(defined($module)) { + if($$allowed_modules_unlimited{$type}) { + print "$file: type ($type) already specificed as an unlimited type\n"; + } elsif(!$$allowed_modules{$type}{$module}) { + $$allowed_modules{$type}{$module} = 1; + $$allowed_modules_limited{$type} = 1; + } else { + print "$file: type ($type) already specificed\n"; + } + } else { + $$allowed_modules_unlimited{$type} = 1; } } else { $$allowed_modules_limited{$type} = 1; } - $$translate_argument{$type} = $kind; + if(defined($$translate_argument{$type}) && $$translate_argument{$type} ne $kind) { + print "$file: type ($type) respecified as different kind ($kind != $$translate_argument{$type})\n"; + } else { + $$translate_argument{$type} = $kind; + } } else { print "$file: file must begin with % statement\n"; exit 1; } } close(IN); - - return $self; } sub get_spec_file_type { @@ -88,7 +125,12 @@ sub read_spec_files { my $win16api = shift; my $win32api = shift; - foreach my $file (split(/\n/, `find $path -name \\*.spec`)) { + my @files = map { + s/^.\/(.*)$/$1/; + $_; + } split(/\n/, `find $path -name \\*.spec`); + + foreach my $file (@files) { my $type = 'winapi'->get_spec_file_type($file); if($type eq "win16") { $win16api->parse_spec_file($file); @@ -100,16 +142,22 @@ sub read_spec_files { sub parse_spec_file { my $self = shift; + + my $output = \${$self->{OUTPUT}}; my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}}; my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}}; my $function_stub = \%{$self->{FUNCTION_STUB}}; my $function_module = \%{$self->{FUNCTION_MODULE}}; + my $file = shift; - + + my %ordinals; my $type; my $module; + $$output->progress("$file"); + open(IN, "< $file") || die "$file: $!\n"; $/ = "\n"; my $header = 1; @@ -126,18 +174,24 @@ sub parse_spec_file { next; } - if(/^\d+\s+(pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/) { - my $calling_convention = $1; - my $external_name = $2; - my $arguments = $3; - my $internal_name = $4; + my $ordinal; + if(/^(\d+)\s+(pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/) { + my $calling_convention = $2; + my $external_name = $3; + my $arguments = $4; + my $internal_name = $5; + + $ordinal = $1; # FIXME: Internal name existing more than once not handled properly $$function_arguments{$internal_name} = $arguments; $$function_calling_convention{$internal_name} = $calling_convention; - $$function_module{$internal_name} = $module; - } elsif(/^\d+\s+stub\s+(\S+)$/) { - my $external_name = $1; + $$function_module{$internal_name} = "$module"; + } elsif(/^(\d+)\s+stub\s+(\S+)$/) { + my $external_name = $2; + + $ordinal = $1; + $$function_stub{$external_name} = 1; $$function_module{$external_name} = $module; } elsif(/^\d+\s+(equate|long|word|extern|forward)/) { @@ -151,13 +205,22 @@ sub parse_spec_file { $lookahead = 1; } } + + if(defined($ordinal)) { + if($ordinals{$ordinal}) { + print "$file: ordinal redefined: $_\n"; + } + $ordinals{$ordinal}++; + } } close(IN); } sub name { my $self = shift; - return $self->{NAME}; + my $name = \${$self->{NAME}}; + + return $$name; } sub is_allowed_kind { @@ -172,6 +235,15 @@ sub is_allowed_kind { } } +sub is_limited_type { + my $self = shift; + my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}}; + + my $type = shift; + + return $$allowed_modules_limited{$type}; +} + sub allowed_type_in_module { my $self = shift; my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; @@ -183,6 +255,34 @@ sub allowed_type_in_module { return !$$allowed_modules_limited{$type} || $$allowed_modules{$type}{$module}; } +sub type_used_in_module { + my $self = shift; + my $used_modules = \%{$self->{USED_MODULES}}; + + my $type = shift; + my $module = shift; + + $$used_modules{$type}{$module} = 1; + + return (); +} + +sub types_not_used { + my $self = shift; + my $used_modules = \%{$self->{USED_MODULES}}; + my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; + + my $not_used; + foreach my $type (sort(keys(%$allowed_modules))) { + foreach my $module (sort(keys(%{$$allowed_modules{$type}}))) { + if(!$$used_modules{$type}{$module}) { + $$not_used{$module}{$type} = 1; + } + } + } + return $not_used; +} + sub translate_argument { my $self = shift; my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; @@ -226,7 +326,7 @@ sub all_functions { sub all_functions_found { my $self = shift; - my $function_found = \$self->{FUNCTION_FOUND}; + my $function_found = \%{$self->{FUNCTION_FOUND}}; return sort(keys(%$function_found)); } @@ -282,11 +382,7 @@ sub function_module { my $name = shift; - if($self->is_function($name)) { - return $$function_module{$name}; - } else { - return undef; - } + return $$function_module{$name}; } sub function_stub { diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check index 564dea2a06c..d6f9e9e8507 100755 --- a/tools/winapi_check/winapi_check +++ b/tools/winapi_check/winapi_check @@ -20,15 +20,19 @@ BEGIN { } @INC = ($winapi_check_dir); - require "winapi.pm"; require "nativeapi.pm"; + require "output.pm"; + require "preprocessor.pm"; + require "winapi.pm"; require "winapi_local.pm"; require "winapi_global.pm"; require "winapi_options.pm"; require "winapi_parser.pm"; - import winapi; import nativeapi; + import output; + import preprocessor; + import winapi; import winapi_local; import winapi_global; import winapi_options; @@ -41,11 +45,13 @@ if($options->help) { exit; } -my $win16api = 'winapi'->new("win16", "$winapi_check_dir/win16api.dat"); -my $win32api = 'winapi'->new("win32", "$winapi_check_dir/win32api.dat"); +my $output = 'output'->new; + +my $win16api = 'winapi'->new($output, "win16", "$winapi_check_dir/win16api.dat", "$winapi_check_dir/win16"); +my $win32api = 'winapi'->new($output, "win32", "$winapi_check_dir/win32api.dat", "$winapi_check_dir/win32"); 'winapi'->read_spec_files($wine_dir, $win16api, $win32api); -my $nativeapi = 'nativeapi'->new("$winapi_check_dir/nativeapi.dat"); +my $nativeapi = 'nativeapi'->new("$winapi_check_dir/nativeapi.dat", "$wine_dir/configure.in", "$wine_dir/include/config.h.in"); for my $name ($win32api->all_functions) { my $module16 = $win16api->function_module($name); @@ -61,13 +67,57 @@ for my $name ($win32api->all_functions) { } } +my %includes; +{ + my @files = map { + s/^.\/(.*)$/$1/; + $_; + } split(/\n/, `find . -name \\*.h`); + + foreach my $file (@files) { + $includes{$file} = { name => $file }; + open(IN, "< $file"); + while() { + if(/^\s*\#\s*include\s*\"(.*?)\"/) { + $includes{$file}{includes}{"include/$1"}++; + } + } + close(IN); + } +} + +my %functions; + +my $progress_output; +my $progress_current=0; +my $progress_max=scalar($options->files); foreach my $file ($options->files) { + $progress_current++; + if($options->progress) { + $output->progress("$file: file $progress_current of $progress_max"); + } + + my $file_dir = $file; + $file_dir =~ s/(.*?)\/[^\/]*$/$1/; + + my $file_type; + if($file_dir =~ /^(libtest|program|rc)/) { + $file_type = "application"; + } elsif($file_dir =~ /^(debug|miscemu)/) { + $file_type = "emulator"; + } elsif($file_dir =~ /^(tools)/) { + $file_type = "tool"; + } else { + $file_type = "library"; + } + my $found_function = sub { 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; @@ -84,16 +134,38 @@ foreach my $file ($options->files) { if($options->local) { my $module16 = $win16api->function_module($name); my $module32 = $win32api->function_module($name); - my $output = sub { + + my $module; + if(defined($module16) && defined($module32)) { + $module = "$module16 & $module32"; + } elsif(defined($module16)) { + $module = $module16; + } elsif(defined($module32)) { + $module = $module32; + } else { + $module = ""; + } + my $output_module = sub { my $module = shift; return sub { my $msg = shift; - print "$file: $module: $return_type $calling_convention $name(" . join(",", @arguments) . "): $msg\n"; + $output->write("$file: $module: $return_type "); + $output->write("$calling_convention ") if $calling_convention; + $output->write("$name(" . join(",", @arguments) . "): $msg\n"); } }; - my $output16 = &$output($module16); - my $output32 = &$output($module32); + my $output16 = &$output_module($module16); + my $output32 = &$output_module($module32); + my $function = $functions{$name}; + $$function{file} = $file; + $$function{return_type} = $return_type; + $$function{calling_convention} = $calling_convention; + $$function{arguments} = [@arguments]; + $$function{module} = $module; + $$function{module16} = $module16; + $$function{module32} = $module32; + if($options->argument) { if($options->win16 && $options->report_module($module16)) { winapi_local::check_arguments $options, $output16, @@ -122,12 +194,145 @@ foreach my $file ($options->files) { } } } + 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}{called_function_names}{$called_name}++; + $functions{$called_name}{called_by_function_names}{$name}++; + } + } else { + undef $_ + } + } + } } - }; - winapi_parser::parse_c_file $options, $file, $found_function; + }; + + my $config = 0; + my $conditional = 0; + my $found_include = sub { + local $_ = shift; + if(/^\"config.h\"/) { + $config++; + } + }; + my $found_conditional = sub { + local $_ = shift; + if(!$nativeapi->is_conditional($_)) { + if(/^HAVE_/ && !/^HAVE_(IPX|MESAGL|BUGGY_MESAGL|WINE_CONSTRUCTOR)$/) + { + $output->write("$file: $_ is not a declared as a conditional\n"); + } + } else { + $conditional++; + if(!$config) { + $output->write("$file: conditional $_ used but config.h is not included\n"); + } + } + }; + my $preprocessor = 'preprocessor'->new($found_include, $found_conditional); + my $found_preprocessor = sub { + my $directive = shift; + my $argument = shift; + + $preprocessor->directive($directive, $argument); + + if($options->config) { + if($directive eq "include") { + if($argument =~ /^<(.*?)>$/) { + my $header = $1; + + if((-e "$wine_dir/include/$header" || -e "$file_dir/$header") && $file_type ne "application") { + $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(!$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"); + } + } 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, but is not protected\n"); + } + } + } + } elsif($preprocessor->is_def($macro)) { + $output->write("$file: #$directive $argument: is protected, but is not a conditional include\n"); + } + } elsif($argument =~ /^"(.*?)"$/) { + my $header = $1; + + if(-e "$file_dir/$header") { + $includes{"$file_dir/$header"}{used}++; + foreach my $name (keys(%{$includes{"$file_dir/$header"}{includes}})) { + $includes{$name}{used}++; + } + } elsif(-e "include/$header") { + $includes{"include/$header"}{used}++; + foreach my $name (keys(%{$includes{"include/$header"}{includes}})) { + $includes{$name}{used}++; + } + } else { + $output->write("$file: #include \"$header\" is not a local include\n"); + } + } + } + } + }; + + winapi_parser::parse_c_file $options, $file, $found_function, $found_preprocessor; + + if($options->config_unnessary) { + if($config && $conditional == 0) { + $output->write("$file: includes config.h but do not use any conditionals\n"); + } + } + + if($options->cross_call) { + my @names = sort(keys(%functions)); + for my $name (@names) { + my @called_names = sort(keys(%{$functions{$name}{called_function_names}})); + my @called_by_names = sort(keys(%{$functions{$name}{called_by_function_names}})); + my $module = $functions{$name}{module}; + my $module16 = $functions{$name}{module16}; + my $module32 = $functions{$name}{module32}; + + if($#called_names >= 0 && (defined($module16) || defined($module32)) ) { + $output->write("$file: $module: $name: \\\n"); + for my $called_name (@called_names) { + my $function; + if($function = $functions{$called_name}) { + $output->write(" $called_name\n"); + } + } + } + } + } } +$output->hide_progress; + if($options->global) { + foreach my $name (sort(keys(%includes))) { + if(!$includes{$name}{used}) { + if($options->include) { + print "$name: include file is never used\n"; + } + } + } + winapi_global::check $options, $win16api, $nativeapi if $options->win16; winapi_global::check $options, $win32api, $nativeapi if $options->win32; } + diff --git a/tools/winapi_check/winapi_global.pm b/tools/winapi_check/winapi_global.pm index 0c4322d4d24..11f44ab2531 100644 --- a/tools/winapi_check/winapi_global.pm +++ b/tools/winapi_check/winapi_global.pm @@ -11,9 +11,9 @@ sub check { if($options->argument) { foreach my $type ($winapi->all_declared_types) { - if(!$winapi->type_found($type) && $type ne "CONTEXT86 *") { - print "*.c: $winver: $type: "; - print "type not used\n"; + if(!$winapi->type_found($type) && !$winapi->is_type_limited($type) && $type ne "CONTEXT86 *") { + print "*.c: $winver: "; + print "type ($type) not used\n"; } } } @@ -21,19 +21,22 @@ sub check { if($options->declared) { foreach my $name ($winapi->all_functions) { if(!$winapi->function_found($name) && !$nativeapi->is_function($name)) { - print "*.c: $winver: $name: "; + my $module = $winapi->function_module($name); + print "*.c: $module: $name: "; print "function declared but not implemented: " . $winapi->function_arguments($name) . "\n"; } } } - if($options->implemented) { - foreach my $name ($winapi->all_functions_found) { - if($winapi->function_stub($name)) { - print "*.c: $winver: $name: "; - print "function implemented but not declared\n"; + if($options->argument_forbidden) { + my $not_used = $winapi->types_not_used; + + foreach my $module (sort(keys(%$not_used))) { + foreach my $type (sort(keys(%{$$not_used{$module}}))) { + print "*.c: $module: type $type not used\n"; } } + } } diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm index 88126bb9386..fe1d356359b 100644 --- a/tools/winapi_check/winapi_local.pm +++ b/tools/winapi_check/winapi_local.pm @@ -14,8 +14,30 @@ sub check_arguments { my $module = $winapi->function_module($name); + if($winapi->name eq "win16") { + my $name16 = $name; + $name16 =~ s/16$//; + if($name16 ne $name && $winapi->function_stub($name16)) { + if($options->implemented) { + &$output("function implemented but declared as stub in .spec file"); + } + return; + } elsif($winapi->function_stub($name)) { + if($options->implemented_win32) { + &$output("32-bit variant of function implemented but declared as stub in .spec file"); + } + return; + } + } elsif($winapi->function_stub($name)) { + if($options->implemented) { + &$output("function implemented but declared as stub in .spec file"); + } + return; + } + my $forbidden_return_type = 0; my $implemented_return_kind; + $winapi->type_used_in_module($return_type,$module); if(!defined($implemented_return_kind = $winapi->translate_argument($return_type))) { if($return_type ne "") { &$output("no translation defined: " . $return_type); @@ -48,8 +70,10 @@ sub check_arguments { $implemented_calling_convention = "cdecl"; } elsif($calling_convention =~ /^VFWAPIV|WINAPIV$/) { $implemented_calling_convention = "varargs"; - } elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI$/) { + } elsif($calling_convention =~ /^__stdcall|VFWAPI|WINAPI$/) { $implemented_calling_convention = "stdcall"; + } else { + $implemented_calling_convention = ""; } } @@ -85,15 +109,12 @@ sub check_arguments { if($name =~ /^CRTDLL__ftol|CRTDLL__CIpow$/) { # ignore - } elsif($#argument_types != $#declared_argument_kinds) { - if($options->argument_count) { - &$output("argument count differs: " . ($#argument_types + 1) . " != " . ($#declared_argument_kinds + 1)); - } } else { my $n = 0; my @argument_kinds = map { my $type = $_; my $kind = "unknown"; + $winapi->type_used_in_module($type,$module); if(!defined($kind = $winapi->translate_argument($type))) { &$output("no translation defined: " . $type); } elsif(!$winapi->is_allowed_kind($kind) || @@ -102,8 +123,13 @@ sub check_arguments { &$output("forbidden argument " . ($n + 1) . " type (" . $type . ")"); } } - $n++; - $kind; + if(defined($kind) && $kind eq "longlong") { + $n+=2; + ("long", "long"); + } else { + $n++; + $kind; + } } @argument_types; for my $n (0..$#argument_kinds) { @@ -123,8 +149,13 @@ sub check_arguments { $argument_types[$n] . " ($argument_kinds[$n]) != " . $declared_argument_kinds[$n]); } } - } + if($#argument_kinds != $#declared_argument_kinds) { + if($options->argument_count) { + &$output("argument count differs: " . ($#argument_types + 1) . " != " . ($#declared_argument_kinds + 1)); + } + } + } if($segmented && $options->shared_segmented && $winapi->is_shared_function($name)) { diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm index 47f58d68aa2..d85b69d5229 100644 --- a/tools/winapi_check/winapi_options.pm +++ b/tools/winapi_check/winapi_options.pm @@ -23,12 +23,17 @@ my %options = ( "help" => { default => 0, description => "help mode" }, "verbose" => { default => 0, description => "verbose mode" }, + "progress" => { default => 1, description => "show progress" }, + "win16" => { default => 1, description => "Win16 checking" }, "win32" => { default => 1, description => "Win32 checking" }, "shared" => { default => 0, description => "show shared functions between Win16 and Win32" }, "shared-segmented" => { default => 0, description => "segmented shared functions between Win16 and Win32 checking" }, + "config" => { default => 1, description => "check configuration include consistancy" }, + "config-unnessary" => { default => 0, parent => "config", description => "check for unnessary #include \"config.h\"" }, + "local" => { default => 1, description => "local checking" }, "module" => { default => { active => 1, filter => 0, hash => {} }, @@ -40,7 +45,7 @@ my %options = ( "argument" => { default => 1, parent => "local", description => "argument checking" }, "argument-count" => { default => 1, parent => "argument", description => "argument count checking" }, "argument-forbidden" => { - default => { active => 0, filter => 0, hash => {} }, + default => { active => 1, filter => 0, hash => {} }, parent => "argument", parser => \&parser_comma_list, description => "argument forbidden checking" @@ -52,12 +57,14 @@ my %options = ( description => "argument kind checking" }, "calling-convention" => { default => 0, parent => "local", description => "calling convention checking" }, - "misplaced" => { default => 0, parent => "local", description => "checking for misplaced functions" }, + "misplaced" => { default => 0, parent => "local", description => "check for misplaced functions" }, + "cross-call" => { default => 0, parent => "local", description => "check for cross calling functions" }, "global" => { default => 1, description => "global checking" }, "declared" => { default => 1, parent => "global", description => "declared checking" }, - "implemented" => { default => 0, parent => "global", description => "implemented checking" } - + "implemented" => { default => 1, parent => "global", description => "implemented checking" }, + "implemented-win32" => { default => 0, parent => "implemented", description => "implemented as win32 checking" }, + "include" => { default => 0, parent => "global", description => "include checking" } ); my %short_options = ( diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm index d6b9c12cbce..ee5a9fe1e77 100644 --- a/tools/winapi_check/winapi_parser.pm +++ b/tools/winapi_check/winapi_parser.pm @@ -6,6 +6,27 @@ sub parse_c_file { my $options = shift; my $file = shift; my $function_found_callback = shift; + my $preprocessor_found_callback = shift; + + my $return_type; + my $calling_convention; + my $function = ""; + my $arguments; + my $statements; + + my $function_begin = sub { + $return_type= shift; + $calling_convention = shift; + $function = shift; + $arguments = shift; + + $statements = ""; + }; + my $function_end = sub { + &$function_found_callback($return_type,$calling_convention,$function,$arguments,$statements); + + $function = ""; + }; my $level = 0; my $again = 0; @@ -44,34 +65,61 @@ sub parse_c_file { if(/^\s*$/) { next; } # remove preprocessor directives - if(s/^\s*\#.*$//m) { $again = 1; next; } + if(s/^\s*\#/\#/m) { + if(/^\\#.*?\\$/m) { + $lookahead = 1; + next; + } elsif(s/^\#\s*(.*?)(\s+(.*?))?\s*$//m) { + if(defined($3)) { + &$preprocessor_found_callback($1, $3); + } else { + &$preprocessor_found_callback($1, ""); + } + $again = 1; + next; + } + } if($level > 0) { - s/^[^\{\}]*//s; - if(/^\{/) { + my $line; + s/^([^\{\}]*)//s; + $line = $1; + if(/^(\{)/) { $_ = $'; $again = 1; + $line .= $1; print "+1: $_\n" if $options->debug >= 2; $level++; - } elsif(/^\}/) { + } elsif(/^(\})/) { $_ = $'; $again = 1; + $line .= $1 if $level > 1; print "-1: $_\n" if $options->debug >= 2; $level--; } + if($line !~ /^\s*$/) { + $statements .= "$line\n"; + } + if($function && $level == 0) { + &$function_end; + } next; - } elsif(/((struct\s+|union\s+|enum\s+)?\w+((\s*\*)+\s*|\s+))(__cdecl|__stdcall|VFWAPIV|VFWAPI|WINAPIV|WINAPI)\s+(\w+(\(\w+\))?)\s*\(([^\)]*)\)\s*(\{|\;)/s) { + } elsif(/((struct\s+|union\s+|enum\s+)?\w+((\s*\*)+\s*|\s+))((__cdecl|__stdcall|VFWAPIV|VFWAPI|WINAPIV|WINAPI)\s+)?(\w+(\(\w+\))?)\s*\(([^\)]*)\)\s*(\{|\;)/s) { $_ = $'; $again = 1; - if($9 eq ";") { + if($10 eq ";") { next; - } elsif($9 eq "{") { + } elsif($10 eq "{") { $level++; } my $return_type = $1; - my $calling_convention = $5; - my $name = $6; - my $arguments = $8; + my $calling_convention = $6; + my $name = $7; + my $arguments = $9; + + if(!defined($calling_convention)) { + $calling_convention = ""; + } $return_type =~ s/\s*$//; $return_type =~ s/\s*\*\s*/*/g; @@ -88,7 +136,8 @@ sub parse_c_file { my $argument = $arguments[$n]; $argument =~ s/^\s*(.*?)\s*$/$1/; #print " " . ($n + 1) . ": '$argument'\n"; - $argument =~ s/^(const(?=\s)|IN(?=\s)|OUT(?=\s)|(\s*))\s*//; + $argument =~ s/^(IN OUT(?=\s)|IN(?=\s)|OUT(?=\s)|\s*)\s*//; + $argument =~ s/^(const(?=\s)|\s*)\s*//; if($argument =~ /^...$/) { $argument = "..."; } elsif($argument =~ /^((struct\s+|union\s+|enum\s+)?\w+)\s*((\*\s*?)*)\s*/) { @@ -107,52 +156,66 @@ sub parse_c_file { if($options->debug) { print "$file: $return_type $calling_convention $name(" . join(",", @arguments) . ")\n"; } - &$function_found_callback($return_type,$calling_convention,$name,\@arguments); + &$function_begin($return_type,$calling_convention,$name,\@arguments); } elsif(/DC_(GET_X_Y|GET_VAL_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; my @arguments = ("HDC16"); - &$function_found_callback($2, "WINAPI", $3, \@arguments); + &$function_begin($2, "WINAPI", $3, \@arguments); + &$function_end; } elsif(/DC_(GET_VAL_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,.*?\)/s) { $_ = $'; $again = 1; my @arguments = ("HDC"); - &$function_found_callback($2, "WINAPI", $3, \@arguments); + &$function_begin($2, "WINAPI", $3, \@arguments); + &$function_end; } elsif(/DC_(GET_VAL_EX)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; my @arguments16 = ("HDC16", "LP" . $5 . "16"); my @arguments32 = ("HDC", "LP" . $5); - &$function_found_callback("BOOL16", "WINAPI", $2 . "16", \@arguments16); - &$function_found_callback("BOOL", "WINAPI", $2, \@arguments32); + &$function_begin("BOOL16", "WINAPI", $2 . "16", \@arguments16); + &$function_end; + &$function_begin("BOOL", "WINAPI", $2, \@arguments32); + &$function_end; } elsif(/DC_(SET_MODE)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; my @arguments16 = ("HDC16", "INT16"); my @arguments32 = ("HDC", "INT"); - &$function_found_callback("INT16", "WINAPI", $2 . "16", \@arguments16); - &$function_found_callback("INT", "WINAPI", $2, \@arguments32); + &$function_begin("INT16", "WINAPI", $2 . "16", \@arguments16); + &$function_end; + &$function_begin("INT", "WINAPI", $2, \@arguments32); + &$function_end; } elsif(/WAVEIN_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; my @arguments16 = ("HWAVEIN16"); my @arguments32 = ("HWAVEIN"); - &$function_found_callback("UINT16", "WINAPI", "waveIn" . $1 . "16", \@arguments16); - &$function_found_callback("UINT", "WINAPI", "waveIn" . $1, \@arguments32); + &$function_begin("UINT16", "WINAPI", "waveIn" . $1 . "16", \@arguments16); + &$function_end; + &$function_begin("UINT", "WINAPI", "waveIn" . $1, \@arguments32); + &$function_end; } elsif(/WAVEOUT_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; my @arguments16 = ("HWAVEOUT16"); my @arguments32 = ("HWAVEOUT"); - &$function_found_callback("UINT16", "WINAPI", "waveOut" . $1 . "16", \@arguments16); - &$function_found_callback("UINT", "WINAPI", "waveOut" . $1, \@arguments32); + &$function_begin("UINT16", "WINAPI", "waveOut" . $1 . "16", \@arguments16); + &$function_end; + &$function_begin("UINT", "WINAPI", "waveOut" . $1, \@arguments32); + &$function_end; } elsif(/WAVEOUT_SHORTCUT_(1|2)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { $_ = $'; $again = 1; if($1 eq "1") { my @arguments16 = ("HWAVEOUT16", $4); my @arguments32 = ("HWAVEOUT", $4); - &$function_found_callback("UINT16", "WINAPI", "waveOut" . $2 . "16", \@arguments16); - &$function_found_callback("UINT", "WINAPI", "waveOut" . $2, \@arguments32); + &$function_begin("UINT16", "WINAPI", "waveOut" . $2 . "16", \@arguments16); + &$function_end; + &$function_begin("UINT", "WINAPI", "waveOut" . $2, \@arguments32); + &$function_end; } elsif($1 eq 2) { my @arguments16 = ("UINT16", $4); my @arguments32 = ("UINT", $4); - &$function_found_callback("UINT16", "WINAPI", "waveOut". $2 . "16", \@arguments16); - &$function_found_callback("UINT", "WINAPI", "waveOut" . $2, \@arguments32) + &$function_begin("UINT16", "WINAPI", "waveOut". $2 . "16", \@arguments16); + &$function_end; + &$function_begin("UINT", "WINAPI", "waveOut" . $2, \@arguments32); + &$function_end; } } elsif(/;/s) { $_ = $'; $again = 1;