Commit 5b3b6d98 authored by Patrik Stridvall's avatar Patrik Stridvall Committed by Alexandre Julliard

- Fixed the long long problem.

- Added configure include consistancy checking. - Added progress indicator. - Began splitting up the win16api.dat and win32api.dat files. - Added various minor checks. - Minor fixes.
parent d7da486c
...@@ -9,17 +9,59 @@ sub new { ...@@ -9,17 +9,59 @@ sub new {
bless ($self, $class); bless ($self, $class);
my $functions = \%{$self->{FUNCTIONS}}; 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"; $/ = "\n";
while(<IN>) { while(<IN>) {
s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
s/^(.*?)\s*#.*$/$1/; # remove comments s/^(.*?)\s*#.*$/$1/; # remove comments
/^$/ && next; # skip empty lines /^$/ && next; # skip empty lines
$$functions{$_} = 1; $$functions{$_}++;
}
close(IN);
my $again = 0;
open(IN, "< $configure_in_file");
local $/ = "\n";
while($again || (defined($_ = <IN>))) {
$again = 0;
chomp;
if(/(.*)\\$/) {
my $line = <IN>;
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(<IN>) {
if(/^\#undef (\S+)$/) {
$$conditionals{$1}++;
}
} }
close(IN); close(IN);
...@@ -35,4 +77,22 @@ sub is_function { ...@@ -35,4 +77,22 @@ sub is_function {
return $$functions{$name}; 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; 1;
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;
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;
...@@ -24,6 +24,7 @@ ULONG ...@@ -24,6 +24,7 @@ ULONG
%longlong %longlong
LARGE_INTEGER LARGE_INTEGER
ULARGE_INTEGER
%ptr %ptr
...@@ -157,6 +158,7 @@ LPPAINTSTRUCT16 ...@@ -157,6 +158,7 @@ LPPAINTSTRUCT16
LPPALETTEENTRY LPPALETTEENTRY
LPPDEVICE LPPDEVICE
LPPOINT16 LPPOINT16
LPPRINTDLG16
LPQUEUESTRUCT16 * LPQUEUESTRUCT16 *
LPRASTERIZER_STATUS LPRASTERIZER_STATUS
LPRECT16 LPRECT16
...@@ -290,7 +292,6 @@ HANDLE16 ...@@ -290,7 +292,6 @@ HANDLE16
HBITMAP16 HBITMAP16
HBRUSH16 HBRUSH16
HCURSOR16 HCURSOR16
HDC16
HDROP16 HDROP16
HDRVR16 HDRVR16
HDWP16 HDWP16
...@@ -330,7 +331,7 @@ WING_DITHER_TYPE ...@@ -330,7 +331,7 @@ WING_DITHER_TYPE
WORD WORD
WPARAM16 WPARAM16
%unknown --forbidden %unknown # --forbidden
BOOL BOOL
FARPROC FARPROC
......
%ptr
AVICOMPRESSOPTIONS *
AVISTREAMINFOA *
AVISTREAMINFOW *
IAVIFile *
LPAVIFILEINFOA
LPAVIFILEINFOW
PAVIFILE
PAVIFILE *
PAVISTREAM
PAVISTREAM *
%long
COLORREF
HBITMAP
HDC
HICON
HWND
\ No newline at end of file
%long
HWND
\ No newline at end of file
%long
COLORREF
HBITMAP
HBRUSH
HCOLORSPACE
HDC
HENHMETAFILE
HFONT
HGDIOBJ
HMETAFILE
HPALETTE
HPEN
HRGN
HWND
%ptr
BITMAP *
BITMAPINFO *
BITMAPINFOHEADER *
%long
HWND
\ No newline at end of file
%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
%long
HDC
HIC
HPALETTE
HWND
%long
CLIPFORMAT
HACCEL
HMENU
HWND
%ptr
CLIPFORMAT *
%long
HPALETTE
%ptr
COLORREF *
%long
HDC
\ No newline at end of file
%long
COLORREF
HBITMAP
HMENU
HICON
HWND
%long
HWND
\ No newline at end of file
%long
COLORREF
HACCEL
HBITMAP
HBRUSH
HCURSOR
HDC
HDESK
HFONT
HICON
HMENU
HMONITOR
HRGN
HWND
%ptr
COLORREF *
%long
HWND
\ No newline at end of file
%long
HWND
\ No newline at end of file
...@@ -13,8 +13,6 @@ BYTE ...@@ -13,8 +13,6 @@ BYTE
CALID CALID
CALTYPE CALTYPE
CHAR CHAR
CLIPFORMAT
COLORREF
COORD COORD
DATE DATE
DIGEST_HANDLE DIGEST_HANDLE
...@@ -25,44 +23,25 @@ FLOAT ...@@ -25,44 +23,25 @@ FLOAT
FOURCC FOURCC
FS_INFORMATION_CLASS FS_INFORMATION_CLASS
GET_FILEEX_INFO_LEVELS GET_FILEEX_INFO_LEVELS
HACCEL
HACMDRIVER
HACMDRIVERID
HACMOBJ
HACMSTREAM
HANDLE HANDLE
HBITMAP
HBRUSH
HCALL HCALL
HCOLORSPACE
HCONV HCONV
HCONVLIST HCONVLIST
HCURSOR
HCRYPTKEY HCRYPTKEY
HDC
HDDEDATA HDDEDATA
HDESK
HDROP HDROP
HDRVR HDRVR
HDSA HDSA
HDWP HDWP
HENHMETAFILE
HFILE HFILE
HFONT
HGDIOBJ
HGLOBAL HGLOBAL
HHOOK HHOOK
HIC
HICON
HIMC
HINSTANCE HINSTANCE
HKEY HKEY
HKL HKL
HLINE HLINE
HLINEAPP HLINEAPP
HLOCAL HLOCAL
HMENU
HMETAFILE
HMIDIIN HMIDIIN
HMIDIOUT HMIDIOUT
HMIDISTRM HMIDISTRM
...@@ -70,23 +49,18 @@ HMIXER ...@@ -70,23 +49,18 @@ HMIXER
HMIXEROBJ HMIXEROBJ
HMMIO HMMIO
HMODULE HMODULE
HMONITOR
HOLEMENU HOLEMENU
HPALETTE
HPEN
HPHONE HPHONE
HPHONEAPP HPHONEAPP
HPROPSHEETPAGE HPROPSHEETPAGE
HPROVIDER HPROVIDER
HRESULT HRESULT
HRGN
HRSRC HRSRC
HSZ HSZ
HTASK HTASK
HWAVEIN HWAVEIN
HWAVEOUT HWAVEOUT
HWINSTA HWINSTA
HWND
INT INT
KEY_INFORMATION_CLASS KEY_INFORMATION_CLASS
KEY_VALUE_INFORMATION_CLASS KEY_VALUE_INFORMATION_CLASS
...@@ -106,7 +80,6 @@ OLECLIPFORMAT ...@@ -106,7 +80,6 @@ OLECLIPFORMAT
OLEOPT_RENDER OLEOPT_RENDER
OLESTATUS OLESTATUS
OLE_SERVER_USE OLE_SERVER_USE
OUT
PHANDLE PHANDLE
PHPROVIDER PHPROVIDER
PIO_APC_ROUTINE PIO_APC_ROUTINE
...@@ -117,6 +90,7 @@ POBJDIR_INFORMATION ...@@ -117,6 +90,7 @@ POBJDIR_INFORMATION
PROCESSINFOCLASS PROCESSINFOCLASS
PTIME_FIELDS PTIME_FIELDS
PTOKEN_PRIVILEGES PTOKEN_PRIVILEGES
REGKIND
REGSAM REGSAM
SC_HANDLE SC_HANDLE
SECTION_INHERIT SECTION_INHERIT
...@@ -150,37 +124,21 @@ time_t ...@@ -150,37 +124,21 @@ time_t
LARGE_INTEGER LARGE_INTEGER
POINT POINT
ULARGE_INTEGER
%ptr %ptr
ABORTPROC ABORTPROC
ACMDRIVERENUMCB
ACMFILTERENUMCBA
ACMFILTERENUMCBW
ACMFILTERTAGENUMCBA
ACMFILTERTAGENUMCBW
ACMFORMATENUMCBA
ACMFORMATENUMCBW
ACMFORMATTAGENUMCBA
ACMFORMATTAGENUMCBW
AVICOMPRESSOPTIONS *
AVISTREAMINFOA *
AVISTREAMINFOW *
BITMAP *
BITMAPINFO *
BITMAPINFOHEADER *
BOOL * BOOL *
BSTR * BSTR *
BYTE * BYTE *
BY_HANDLE_FILE_INFORMATION * BY_HANDLE_FILE_INFORMATION *
CALINFO_ENUMPROCA CALINFO_ENUMPROCA
CHAR * CHAR *
CLIPFORMAT *
CLSID * CLSID *
CODEPAGE_ENUMPROCA CODEPAGE_ENUMPROCA
CODEPAGE_ENUMPROCW CODEPAGE_ENUMPROCW
COLORADJUSTMENT * COLORADJUSTMENT *
COLORREF *
CONST CONST
CONTEXT * CONTEXT *
COSERVERINFO * COSERVERINFO *
...@@ -238,6 +196,7 @@ HMENU * ...@@ -238,6 +196,7 @@ HMENU *
HMIDIIN * HMIDIIN *
HMIDIOUT * HMIDIOUT *
HMIDISTRM * HMIDISTRM *
HMODULE *
HMRU HMRU
HOOKPROC HOOKPROC
HPCSTR HPCSTR
...@@ -254,6 +213,8 @@ IDropTarget * ...@@ -254,6 +213,8 @@ IDropTarget *
ILockBytes * ILockBytes *
IMAGEINFO * IMAGEINFO *
IMAGELISTDRAWPARAMS * IMAGELISTDRAWPARAMS *
IMoniker *
IMoniker **
INPUT_RECORD * INPUT_RECORD *
INT * INT *
IPersistStream * IPersistStream *
...@@ -283,8 +244,6 @@ LPACCEL ...@@ -283,8 +244,6 @@ LPACCEL
LPAUTHDLGSTRUCTA LPAUTHDLGSTRUCTA
LPAUXCAPSA LPAUXCAPSA
LPAUXCAPSW LPAUXCAPSW
LPAVIFILEINFOA
LPAVIFILEINFOW
LPBC * LPBC *
LPBITMAPINFOHEADER LPBITMAPINFOHEADER
LPBOOL LPBOOL
...@@ -327,6 +286,7 @@ LPCWSTR * ...@@ -327,6 +286,7 @@ LPCWSTR *
LPDATAADVISEHOLDER * LPDATAADVISEHOLDER *
LPDATAOBJECT LPDATAOBJECT
LPDCB LPDCB
LPDCB *
LPDDENUMCALLBACKA LPDDENUMCALLBACKA
LPDDENUMCALLBACKEXA LPDDENUMCALLBACKEXA
LPDDENUMCALLBACKEXW LPDDENUMCALLBACKEXW
...@@ -434,8 +394,10 @@ LPMIXERLINECONTROLSW ...@@ -434,8 +394,10 @@ LPMIXERLINECONTROLSW
LPMIXERLINEW LPMIXERLINEW
LPMMCKINFO LPMMCKINFO
LPMMIOPROC LPMMIOPROC
LPMMIOPROC16
LPMMTIME LPMMTIME
LPMODULEENTRY LPMODULEENTRY
LPMODULEINFO
LPMONIKER LPMONIKER
LPMONIKER * LPMONIKER *
LPMONITORINFO LPMONITORINFO
...@@ -579,31 +541,12 @@ PACE_HEADER ...@@ -579,31 +541,12 @@ PACE_HEADER
PACE_HEADER * PACE_HEADER *
PACL PACL
PACL * PACL *
PACMDRIVERDETAILSA
PACMDRIVERDETAILSW
PACMFILTERCHOOSEA
PACMFILTERCHOOSEW
PACMFILTERDETAILSA
PACMFILTERDETAILSW
PACMFILTERTAGDETAILSA
PACMFILTERTAGDETAILSW
PACMFORMATCHOOSEA
PACMFORMATCHOOSEW
PACMFORMATDETAILSA
PACMFORMATDETAILSW
PACMFORMATTAGDETAILSA
PACMFORMATTAGDETAILSW
PACMSTREAMHEADER
PAINTSTRUCT * PAINTSTRUCT *
PALETTEENTRY * PALETTEENTRY *
PANSI_STRING PANSI_STRING
PAPCFUNC PAPCFUNC
PAPI_VERSION PAPI_VERSION
PAPPBARDATA PAPPBARDATA
PAVIFILE
PAVIFILE *
PAVISTREAM
PAVISTREAM *
PBOOLEAN PBOOLEAN
PBYTE PBYTE
PCHAR PCHAR
...@@ -623,9 +566,6 @@ PFUNCTION_TABLE_ACCESS_ROUTINE ...@@ -623,9 +566,6 @@ PFUNCTION_TABLE_ACCESS_ROUTINE
PGENERIC_MAPPING PGENERIC_MAPPING
PGETFRAME PGETFRAME
PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE
PHACMDRIVER
PHACMDRIVERID
PHACMSTREAM
PHONECALLBACK PHONECALLBACK
PIMAGEHLP_MODULE PIMAGEHLP_MODULE
PIMAGEHLP_STATUS_ROUTINE PIMAGEHLP_STATUS_ROUTINE
...@@ -646,7 +586,9 @@ POBJECT_ATTRIBUTES ...@@ -646,7 +586,9 @@ POBJECT_ATTRIBUTES
POINT * POINT *
PPOLYTEXTA PPOLYTEXTA
PPOLYTEXTW PPOLYTEXTW
PPSAPI_WS_WATCH_INFORMATION
PPRIVILEGE_SET PPRIVILEGE_SET
PPROCESS_MEMORY_COUNTERS
PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE
PRTL_HEAP_DEFINITION PRTL_HEAP_DEFINITION
PROPENUMPROCA PROPENUMPROCA
......
...@@ -8,18 +8,48 @@ sub new { ...@@ -8,18 +8,48 @@ sub new {
my $self = {}; my $self = {};
bless ($self, $class); 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_kind = \%{$self->{ALLOWED_KIND}};
my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}}; my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
$self->{NAME} = shift;
my $file = shift; my $file = shift;
my $module = shift;
my @modules;
my $kind; my $kind;
my $forbidden = 0; my $forbidden = 0;
$$output->progress("$file");
open(IN, "< $file") || die "$file: $!\n"; open(IN, "< $file") || die "$file: $!\n";
$/ = "\n"; $/ = "\n";
while(<IN>) { while(<IN>) {
...@@ -29,34 +59,41 @@ sub new { ...@@ -29,34 +59,41 @@ sub new {
if(s/^%(\S+)\s*//) { if(s/^%(\S+)\s*//) {
$kind = $1; $kind = $1;
@modules = ();
$forbidden = 0; $forbidden = 0;
$$allowed_kind{$kind} = 1; $$allowed_kind{$kind} = 1;
if(/^--module=(\S*)/) { if(/^--forbidden/) {
@modules = split(/,/, $1);
} elsif(/^--forbidden/) {
$forbidden = 1; $forbidden = 1;
} }
} elsif(defined($kind)) { } elsif(defined($kind)) {
my $type = $_; my $type = $_;
if(!$forbidden) { if(!$forbidden) {
for my $module (@modules) { if(defined($module)) {
$$allowed_modules_limited{$type} = 1; if($$allowed_modules_unlimited{$type}) {
$$allowed_modules{$type}{$module} = 1; 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 { } else {
$$allowed_modules_limited{$type} = 1; $$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 { } else {
print "$file: file must begin with %<type> statement\n"; print "$file: file must begin with %<type> statement\n";
exit 1; exit 1;
} }
} }
close(IN); close(IN);
return $self;
} }
sub get_spec_file_type { sub get_spec_file_type {
...@@ -88,7 +125,12 @@ sub read_spec_files { ...@@ -88,7 +125,12 @@ sub read_spec_files {
my $win16api = shift; my $win16api = shift;
my $win32api = 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); my $type = 'winapi'->get_spec_file_type($file);
if($type eq "win16") { if($type eq "win16") {
$win16api->parse_spec_file($file); $win16api->parse_spec_file($file);
...@@ -100,16 +142,22 @@ sub read_spec_files { ...@@ -100,16 +142,22 @@ sub read_spec_files {
sub parse_spec_file { sub parse_spec_file {
my $self = shift; my $self = shift;
my $output = \${$self->{OUTPUT}};
my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}}; my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}};
my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}}; my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
my $function_stub = \%{$self->{FUNCTION_STUB}}; my $function_stub = \%{$self->{FUNCTION_STUB}};
my $function_module = \%{$self->{FUNCTION_MODULE}}; my $function_module = \%{$self->{FUNCTION_MODULE}};
my $file = shift; my $file = shift;
my %ordinals;
my $type; my $type;
my $module; my $module;
$$output->progress("$file");
open(IN, "< $file") || die "$file: $!\n"; open(IN, "< $file") || die "$file: $!\n";
$/ = "\n"; $/ = "\n";
my $header = 1; my $header = 1;
...@@ -126,18 +174,24 @@ sub parse_spec_file { ...@@ -126,18 +174,24 @@ sub parse_spec_file {
next; next;
} }
if(/^\d+\s+(pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/) { my $ordinal;
my $calling_convention = $1; if(/^(\d+)\s+(pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/) {
my $external_name = $2; my $calling_convention = $2;
my $arguments = $3; my $external_name = $3;
my $internal_name = $4; my $arguments = $4;
my $internal_name = $5;
$ordinal = $1;
# FIXME: Internal name existing more than once not handled properly # FIXME: Internal name existing more than once not handled properly
$$function_arguments{$internal_name} = $arguments; $$function_arguments{$internal_name} = $arguments;
$$function_calling_convention{$internal_name} = $calling_convention; $$function_calling_convention{$internal_name} = $calling_convention;
$$function_module{$internal_name} = $module; $$function_module{$internal_name} = "$module";
} elsif(/^\d+\s+stub\s+(\S+)$/) { } elsif(/^(\d+)\s+stub\s+(\S+)$/) {
my $external_name = $1; my $external_name = $2;
$ordinal = $1;
$$function_stub{$external_name} = 1; $$function_stub{$external_name} = 1;
$$function_module{$external_name} = $module; $$function_module{$external_name} = $module;
} elsif(/^\d+\s+(equate|long|word|extern|forward)/) { } elsif(/^\d+\s+(equate|long|word|extern|forward)/) {
...@@ -151,13 +205,22 @@ sub parse_spec_file { ...@@ -151,13 +205,22 @@ sub parse_spec_file {
$lookahead = 1; $lookahead = 1;
} }
} }
if(defined($ordinal)) {
if($ordinals{$ordinal}) {
print "$file: ordinal redefined: $_\n";
}
$ordinals{$ordinal}++;
}
} }
close(IN); close(IN);
} }
sub name { sub name {
my $self = shift; my $self = shift;
return $self->{NAME}; my $name = \${$self->{NAME}};
return $$name;
} }
sub is_allowed_kind { sub is_allowed_kind {
...@@ -172,6 +235,15 @@ 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 { sub allowed_type_in_module {
my $self = shift; my $self = shift;
my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
...@@ -183,6 +255,34 @@ sub allowed_type_in_module { ...@@ -183,6 +255,34 @@ sub allowed_type_in_module {
return !$$allowed_modules_limited{$type} || $$allowed_modules{$type}{$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 { sub translate_argument {
my $self = shift; my $self = shift;
my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
...@@ -226,7 +326,7 @@ sub all_functions { ...@@ -226,7 +326,7 @@ sub all_functions {
sub all_functions_found { sub all_functions_found {
my $self = shift; my $self = shift;
my $function_found = \$self->{FUNCTION_FOUND}; my $function_found = \%{$self->{FUNCTION_FOUND}};
return sort(keys(%$function_found)); return sort(keys(%$function_found));
} }
...@@ -282,11 +382,7 @@ sub function_module { ...@@ -282,11 +382,7 @@ sub function_module {
my $name = shift; my $name = shift;
if($self->is_function($name)) { return $$function_module{$name};
return $$function_module{$name};
} else {
return undef;
}
} }
sub function_stub { sub function_stub {
......
...@@ -20,15 +20,19 @@ BEGIN { ...@@ -20,15 +20,19 @@ BEGIN {
} }
@INC = ($winapi_check_dir); @INC = ($winapi_check_dir);
require "winapi.pm";
require "nativeapi.pm"; require "nativeapi.pm";
require "output.pm";
require "preprocessor.pm";
require "winapi.pm";
require "winapi_local.pm"; require "winapi_local.pm";
require "winapi_global.pm"; require "winapi_global.pm";
require "winapi_options.pm"; require "winapi_options.pm";
require "winapi_parser.pm"; require "winapi_parser.pm";
import winapi;
import nativeapi; import nativeapi;
import output;
import preprocessor;
import winapi;
import winapi_local; import winapi_local;
import winapi_global; import winapi_global;
import winapi_options; import winapi_options;
...@@ -41,11 +45,13 @@ if($options->help) { ...@@ -41,11 +45,13 @@ if($options->help) {
exit; exit;
} }
my $win16api = 'winapi'->new("win16", "$winapi_check_dir/win16api.dat"); my $output = 'output'->new;
my $win32api = 'winapi'->new("win32", "$winapi_check_dir/win32api.dat");
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); '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) { for my $name ($win32api->all_functions) {
my $module16 = $win16api->function_module($name); my $module16 = $win16api->function_module($name);
...@@ -61,13 +67,57 @@ for my $name ($win32api->all_functions) { ...@@ -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(<IN>) {
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) { 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 $found_function = sub {
my $return_type = shift; my $return_type = shift;
my $calling_convention = shift; my $calling_convention = shift;
my $name = shift; my $name = shift;
my $refarguments = shift; my $refarguments = shift;
my @arguments = @$refarguments; my @arguments = @$refarguments;
my $statements = shift;
if($options->global) { if($options->global) {
$win16api->found_type($return_type) if $options->win16; $win16api->found_type($return_type) if $options->win16;
...@@ -84,16 +134,38 @@ foreach my $file ($options->files) { ...@@ -84,16 +134,38 @@ foreach my $file ($options->files) {
if($options->local) { if($options->local) {
my $module16 = $win16api->function_module($name); my $module16 = $win16api->function_module($name);
my $module32 = $win32api->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; my $module = shift;
return sub { return sub {
my $msg = shift; 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 $output16 = &$output_module($module16);
my $output32 = &$output($module32); 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->argument) {
if($options->win16 && $options->report_module($module16)) { if($options->win16 && $options->report_module($module16)) {
winapi_local::check_arguments $options, $output16, winapi_local::check_arguments $options, $output16,
...@@ -122,12 +194,145 @@ foreach my $file ($options->files) { ...@@ -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 $_
}
}
}
}
};
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");
}
} }
}; };
winapi_parser::parse_c_file $options, $file, $found_function; 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) { 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, $win16api, $nativeapi if $options->win16;
winapi_global::check $options, $win32api, $nativeapi if $options->win32; winapi_global::check $options, $win32api, $nativeapi if $options->win32;
} }
...@@ -11,9 +11,9 @@ sub check { ...@@ -11,9 +11,9 @@ sub check {
if($options->argument) { if($options->argument) {
foreach my $type ($winapi->all_declared_types) { foreach my $type ($winapi->all_declared_types) {
if(!$winapi->type_found($type) && $type ne "CONTEXT86 *") { if(!$winapi->type_found($type) && !$winapi->is_type_limited($type) && $type ne "CONTEXT86 *") {
print "*.c: $winver: $type: "; print "*.c: $winver: ";
print "type not used\n"; print "type ($type) not used\n";
} }
} }
} }
...@@ -21,19 +21,22 @@ sub check { ...@@ -21,19 +21,22 @@ sub check {
if($options->declared) { if($options->declared) {
foreach my $name ($winapi->all_functions) { foreach my $name ($winapi->all_functions) {
if(!$winapi->function_found($name) && !$nativeapi->is_function($name)) { 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"; print "function declared but not implemented: " . $winapi->function_arguments($name) . "\n";
} }
} }
} }
if($options->implemented) { if($options->argument_forbidden) {
foreach my $name ($winapi->all_functions_found) { my $not_used = $winapi->types_not_used;
if($winapi->function_stub($name)) {
print "*.c: $winver: $name: "; foreach my $module (sort(keys(%$not_used))) {
print "function implemented but not declared\n"; foreach my $type (sort(keys(%{$$not_used{$module}}))) {
print "*.c: $module: type $type not used\n";
} }
} }
} }
} }
......
...@@ -14,8 +14,30 @@ sub check_arguments { ...@@ -14,8 +14,30 @@ sub check_arguments {
my $module = $winapi->function_module($name); 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 $forbidden_return_type = 0;
my $implemented_return_kind; my $implemented_return_kind;
$winapi->type_used_in_module($return_type,$module);
if(!defined($implemented_return_kind = $winapi->translate_argument($return_type))) { if(!defined($implemented_return_kind = $winapi->translate_argument($return_type))) {
if($return_type ne "") { if($return_type ne "") {
&$output("no translation defined: " . $return_type); &$output("no translation defined: " . $return_type);
...@@ -48,8 +70,10 @@ sub check_arguments { ...@@ -48,8 +70,10 @@ sub check_arguments {
$implemented_calling_convention = "cdecl"; $implemented_calling_convention = "cdecl";
} elsif($calling_convention =~ /^VFWAPIV|WINAPIV$/) { } elsif($calling_convention =~ /^VFWAPIV|WINAPIV$/) {
$implemented_calling_convention = "varargs"; $implemented_calling_convention = "varargs";
} elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI$/) { } elsif($calling_convention =~ /^__stdcall|VFWAPI|WINAPI$/) {
$implemented_calling_convention = "stdcall"; $implemented_calling_convention = "stdcall";
} else {
$implemented_calling_convention = "<default>";
} }
} }
...@@ -85,15 +109,12 @@ sub check_arguments { ...@@ -85,15 +109,12 @@ sub check_arguments {
if($name =~ /^CRTDLL__ftol|CRTDLL__CIpow$/) { if($name =~ /^CRTDLL__ftol|CRTDLL__CIpow$/) {
# ignore # ignore
} elsif($#argument_types != $#declared_argument_kinds) {
if($options->argument_count) {
&$output("argument count differs: " . ($#argument_types + 1) . " != " . ($#declared_argument_kinds + 1));
}
} else { } else {
my $n = 0; my $n = 0;
my @argument_kinds = map { my @argument_kinds = map {
my $type = $_; my $type = $_;
my $kind = "unknown"; my $kind = "unknown";
$winapi->type_used_in_module($type,$module);
if(!defined($kind = $winapi->translate_argument($type))) { if(!defined($kind = $winapi->translate_argument($type))) {
&$output("no translation defined: " . $type); &$output("no translation defined: " . $type);
} elsif(!$winapi->is_allowed_kind($kind) || } elsif(!$winapi->is_allowed_kind($kind) ||
...@@ -102,8 +123,13 @@ sub check_arguments { ...@@ -102,8 +123,13 @@ sub check_arguments {
&$output("forbidden argument " . ($n + 1) . " type (" . $type . ")"); &$output("forbidden argument " . ($n + 1) . " type (" . $type . ")");
} }
} }
$n++; if(defined($kind) && $kind eq "longlong") {
$kind; $n+=2;
("long", "long");
} else {
$n++;
$kind;
}
} @argument_types; } @argument_types;
for my $n (0..$#argument_kinds) { for my $n (0..$#argument_kinds) {
...@@ -123,8 +149,13 @@ sub check_arguments { ...@@ -123,8 +149,13 @@ sub check_arguments {
$argument_types[$n] . " ($argument_kinds[$n]) != " . $declared_argument_kinds[$n]); $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)) { if($segmented && $options->shared_segmented && $winapi->is_shared_function($name)) {
......
...@@ -23,12 +23,17 @@ my %options = ( ...@@ -23,12 +23,17 @@ my %options = (
"help" => { default => 0, description => "help mode" }, "help" => { default => 0, description => "help mode" },
"verbose" => { default => 0, description => "verbose mode" }, "verbose" => { default => 0, description => "verbose mode" },
"progress" => { default => 1, description => "show progress" },
"win16" => { default => 1, description => "Win16 checking" }, "win16" => { default => 1, description => "Win16 checking" },
"win32" => { default => 1, description => "Win32 checking" }, "win32" => { default => 1, description => "Win32 checking" },
"shared" => { default => 0, description => "show shared functions between Win16 and Win32" }, "shared" => { default => 0, description => "show shared functions between Win16 and Win32" },
"shared-segmented" => { default => 0, description => "segmented shared functions between Win16 and Win32 checking" }, "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" }, "local" => { default => 1, description => "local checking" },
"module" => { "module" => {
default => { active => 1, filter => 0, hash => {} }, default => { active => 1, filter => 0, hash => {} },
...@@ -40,7 +45,7 @@ my %options = ( ...@@ -40,7 +45,7 @@ my %options = (
"argument" => { default => 1, parent => "local", description => "argument checking" }, "argument" => { default => 1, parent => "local", description => "argument checking" },
"argument-count" => { default => 1, parent => "argument", description => "argument count checking" }, "argument-count" => { default => 1, parent => "argument", description => "argument count checking" },
"argument-forbidden" => { "argument-forbidden" => {
default => { active => 0, filter => 0, hash => {} }, default => { active => 1, filter => 0, hash => {} },
parent => "argument", parent => "argument",
parser => \&parser_comma_list, parser => \&parser_comma_list,
description => "argument forbidden checking" description => "argument forbidden checking"
...@@ -52,12 +57,14 @@ my %options = ( ...@@ -52,12 +57,14 @@ my %options = (
description => "argument kind checking" description => "argument kind checking"
}, },
"calling-convention" => { default => 0, parent => "local", description => "calling convention 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" }, "global" => { default => 1, description => "global checking" },
"declared" => { default => 1, parent => "global", description => "declared 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 = ( my %short_options = (
......
...@@ -6,6 +6,27 @@ sub parse_c_file { ...@@ -6,6 +6,27 @@ sub parse_c_file {
my $options = shift; my $options = shift;
my $file = shift; my $file = shift;
my $function_found_callback = 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 $level = 0;
my $again = 0; my $again = 0;
...@@ -44,34 +65,61 @@ sub parse_c_file { ...@@ -44,34 +65,61 @@ sub parse_c_file {
if(/^\s*$/) { next; } if(/^\s*$/) { next; }
# remove preprocessor directives # 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) if($level > 0)
{ {
s/^[^\{\}]*//s; my $line;
if(/^\{/) { s/^([^\{\}]*)//s;
$line = $1;
if(/^(\{)/) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
$line .= $1;
print "+1: $_\n" if $options->debug >= 2; print "+1: $_\n" if $options->debug >= 2;
$level++; $level++;
} elsif(/^\}/) { } elsif(/^(\})/) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
$line .= $1 if $level > 1;
print "-1: $_\n" if $options->debug >= 2; print "-1: $_\n" if $options->debug >= 2;
$level--; $level--;
} }
if($line !~ /^\s*$/) {
$statements .= "$line\n";
}
if($function && $level == 0) {
&$function_end;
}
next; 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; $_ = $'; $again = 1;
if($9 eq ";") { if($10 eq ";") {
next; next;
} elsif($9 eq "{") { } elsif($10 eq "{") {
$level++; $level++;
} }
my $return_type = $1; my $return_type = $1;
my $calling_convention = $5; my $calling_convention = $6;
my $name = $6; my $name = $7;
my $arguments = $8; my $arguments = $9;
if(!defined($calling_convention)) {
$calling_convention = "";
}
$return_type =~ s/\s*$//; $return_type =~ s/\s*$//;
$return_type =~ s/\s*\*\s*/*/g; $return_type =~ s/\s*\*\s*/*/g;
...@@ -88,7 +136,8 @@ sub parse_c_file { ...@@ -88,7 +136,8 @@ sub parse_c_file {
my $argument = $arguments[$n]; my $argument = $arguments[$n];
$argument =~ s/^\s*(.*?)\s*$/$1/; $argument =~ s/^\s*(.*?)\s*$/$1/;
#print " " . ($n + 1) . ": '$argument'\n"; #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 =~ /^...$/) { if($argument =~ /^...$/) {
$argument = "..."; $argument = "...";
} elsif($argument =~ /^((struct\s+|union\s+|enum\s+)?\w+)\s*((\*\s*?)*)\s*/) { } elsif($argument =~ /^((struct\s+|union\s+|enum\s+)?\w+)\s*((\*\s*?)*)\s*/) {
...@@ -107,52 +156,66 @@ sub parse_c_file { ...@@ -107,52 +156,66 @@ sub parse_c_file {
if($options->debug) { if($options->debug) {
print "$file: $return_type $calling_convention $name(" . join(",", @arguments) . ")\n"; 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) { } elsif(/DC_(GET_X_Y|GET_VAL_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
my @arguments = ("HDC16"); 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) { } elsif(/DC_(GET_VAL_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,.*?\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
my @arguments = ("HDC"); 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) { } elsif(/DC_(GET_VAL_EX)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
my @arguments16 = ("HDC16", "LP" . $5 . "16"); my @arguments16 = ("HDC16", "LP" . $5 . "16");
my @arguments32 = ("HDC", "LP" . $5); my @arguments32 = ("HDC", "LP" . $5);
&$function_found_callback("BOOL16", "WINAPI", $2 . "16", \@arguments16); &$function_begin("BOOL16", "WINAPI", $2 . "16", \@arguments16);
&$function_found_callback("BOOL", "WINAPI", $2, \@arguments32); &$function_end;
&$function_begin("BOOL", "WINAPI", $2, \@arguments32);
&$function_end;
} elsif(/DC_(SET_MODE)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { } elsif(/DC_(SET_MODE)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
my @arguments16 = ("HDC16", "INT16"); my @arguments16 = ("HDC16", "INT16");
my @arguments32 = ("HDC", "INT"); my @arguments32 = ("HDC", "INT");
&$function_found_callback("INT16", "WINAPI", $2 . "16", \@arguments16); &$function_begin("INT16", "WINAPI", $2 . "16", \@arguments16);
&$function_found_callback("INT", "WINAPI", $2, \@arguments32); &$function_end;
&$function_begin("INT", "WINAPI", $2, \@arguments32);
&$function_end;
} elsif(/WAVEIN_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) { } elsif(/WAVEIN_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
my @arguments16 = ("HWAVEIN16"); my @arguments16 = ("HWAVEIN16");
my @arguments32 = ("HWAVEIN"); my @arguments32 = ("HWAVEIN");
&$function_found_callback("UINT16", "WINAPI", "waveIn" . $1 . "16", \@arguments16); &$function_begin("UINT16", "WINAPI", "waveIn" . $1 . "16", \@arguments16);
&$function_found_callback("UINT", "WINAPI", "waveIn" . $1, \@arguments32); &$function_end;
&$function_begin("UINT", "WINAPI", "waveIn" . $1, \@arguments32);
&$function_end;
} elsif(/WAVEOUT_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) { } elsif(/WAVEOUT_SHORTCUT_0\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
my @arguments16 = ("HWAVEOUT16"); my @arguments16 = ("HWAVEOUT16");
my @arguments32 = ("HWAVEOUT"); my @arguments32 = ("HWAVEOUT");
&$function_found_callback("UINT16", "WINAPI", "waveOut" . $1 . "16", \@arguments16); &$function_begin("UINT16", "WINAPI", "waveOut" . $1 . "16", \@arguments16);
&$function_found_callback("UINT", "WINAPI", "waveOut" . $1, \@arguments32); &$function_end;
&$function_begin("UINT", "WINAPI", "waveOut" . $1, \@arguments32);
&$function_end;
} elsif(/WAVEOUT_SHORTCUT_(1|2)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { } elsif(/WAVEOUT_SHORTCUT_(1|2)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
if($1 eq "1") { if($1 eq "1") {
my @arguments16 = ("HWAVEOUT16", $4); my @arguments16 = ("HWAVEOUT16", $4);
my @arguments32 = ("HWAVEOUT", $4); my @arguments32 = ("HWAVEOUT", $4);
&$function_found_callback("UINT16", "WINAPI", "waveOut" . $2 . "16", \@arguments16); &$function_begin("UINT16", "WINAPI", "waveOut" . $2 . "16", \@arguments16);
&$function_found_callback("UINT", "WINAPI", "waveOut" . $2, \@arguments32); &$function_end;
&$function_begin("UINT", "WINAPI", "waveOut" . $2, \@arguments32);
&$function_end;
} elsif($1 eq 2) { } elsif($1 eq 2) {
my @arguments16 = ("UINT16", $4); my @arguments16 = ("UINT16", $4);
my @arguments32 = ("UINT", $4); my @arguments32 = ("UINT", $4);
&$function_found_callback("UINT16", "WINAPI", "waveOut". $2 . "16", \@arguments16); &$function_begin("UINT16", "WINAPI", "waveOut". $2 . "16", \@arguments16);
&$function_found_callback("UINT", "WINAPI", "waveOut" . $2, \@arguments32) &$function_end;
&$function_begin("UINT", "WINAPI", "waveOut" . $2, \@arguments32);
&$function_end;
} }
} elsif(/;/s) { } elsif(/;/s) {
$_ = $'; $again = 1; $_ = $'; $again = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment