From 37fd2d1c85c86b1a1536e733f30ab93176219505 Mon Sep 17 00:00:00 2001 From: Patrik Stridvall Date: Thu, 23 Sep 1999 15:14:20 +0000 Subject: [PATCH] Made a new improved version of winapi-check in perl. --- tools/winapi-check | 49 -- tools/winapi_check/nativeapi.dat | 217 ++++++++ tools/winapi_check/nativeapi.pm | 38 ++ tools/winapi_check/parser.pm | 184 +++++++ tools/winapi_check/win16api.dat | 348 ++++++++++++ tools/winapi_check/win32api.dat | 785 +++++++++++++++++++++++++++ tools/winapi_check/winapi.pm | 318 +++++++++++ tools/winapi_check/winapi_check | 118 ++++ tools/winapi_check/winapi_global.pm | 41 ++ tools/winapi_check/winapi_local.pm | 136 +++++ tools/winapi_check/winapi_options.pm | 272 ++++++++++ tools/winapi_check/winapi_parser.pm | 161 ++++++ 12 files changed, 2618 insertions(+), 49 deletions(-) delete mode 100755 tools/winapi-check create mode 100644 tools/winapi_check/nativeapi.dat create mode 100644 tools/winapi_check/nativeapi.pm create mode 100644 tools/winapi_check/parser.pm create mode 100644 tools/winapi_check/win16api.dat create mode 100644 tools/winapi_check/win32api.dat create mode 100644 tools/winapi_check/winapi.pm create mode 100755 tools/winapi_check/winapi_check create mode 100644 tools/winapi_check/winapi_global.pm create mode 100644 tools/winapi_check/winapi_local.pm create mode 100644 tools/winapi_check/winapi_options.pm create mode 100644 tools/winapi_check/winapi_parser.pm diff --git a/tools/winapi-check b/tools/winapi-check deleted file mode 100755 index 346d3e22361..00000000000 --- a/tools/winapi-check +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# This quick and dirty script prints the names of functions that don't have a -# WINAPI in its header declaration or don't appear in any .c file at all. -# I don't think it's very intelligent to use it when having < 64 MB ;) -# FIXME: This script skips .spec function entries that occupy two or more -# .spec lines ! - -if [ ! -e ./ChangeLog ] ; then - echo You are not in Wine main directory ! - exit -fi -echo crtdll.spec, ntdll.spec and wsock32.spec will be mentioned many times, -echo as they use original UNIX functions that don\'t exist in Wine .c code. -echo -FIND_LIST="`find . -name "*.c"`" -for i in if1632/*.spec relay32/*.spec -do -# skip wprocs.spec, as it contains many funcs that don't need a WINAPI - if [ $i = "if1632/wprocs.spec" ] ; then - continue - fi - LINE="`egrep "stdcall|cdecl|pascal|register" $i|grep -v "^#"|tr -d " "|tr "\n" " "`" - for j in $LINE - do - if [ -n "`echo "$j"|grep \)`" ] ; then - FUNC="`echo $j|cut -f2 -d\)|cut -f1 -d'#'`" - if [ -n "$FUNC" ] ; then - if [ -z "`grep -B 1 $FUNC $FIND_LIST|egrep "WINAPI|__cdecl|VFWAPI|DC_GET_VAL|DC_SET_MODE|REGS_ENTRYPOINT"`" ] ; then - case $FUNC in # "black list" - "GetBrushOrgEx16" ) ;; - "GetCurrentPositionEx16" ) ;; - "GetViewportExtEx16" ) ;; - "GetViewportOrgEx16" ) ;; - "GetWindowExtEx16" ) ;; - "GetWindowOrgEx16" ) ;; - - "GetBrushOrgEx32" ) ;; - "GetCurrentPositionEx32" ) ;; - "GetViewportExtEx32" ) ;; - "GetViewportOrgEx32" ) ;; - "GetWindowExtEx32" ) ;; - "GetWindowOrgEx32" ) ;; - * ) echo "$i: $FUNC" ;; - esac - fi - fi - fi - done -done diff --git a/tools/winapi_check/nativeapi.dat b/tools/winapi_check/nativeapi.dat new file mode 100644 index 00000000000..8a3de0f9e5d --- /dev/null +++ b/tools/winapi_check/nativeapi.dat @@ -0,0 +1,217 @@ +__ctype +__divdi3 +__eprintf +__fixunsdfdi +__flsbuf +__iob +__moddi3 +_environ +_exit +_fxstat +_lwp_create +_lwp_exit +_lwp_makecontext +_lxstat +_sysconf +_xmknod +_xstat +abs +access +acos +asctime +asin +atan +atan2 +atexit +atof +atoi +atol +bsearch +bzero +calloc +ceil +cfgetospeed +chmod +close +closedir +cos +cosh +ctime +div +dup +dup2 +environ +errno +execlp +execvp +exit +exp +fabs +fclose +fcntl +fdopen +feof +fflush +ffs +fgetc +fgetpos +fgets +floor +fmod +fopen +fork +fprintf +fputc +fputs +fread +free +frexp +fseek +fsetpos +fsync +ftruncate +fwrite +getcwd +getenv +getlogin +getnetbyname +getpid +getpwuid +gettimeofday +getuid +gmtime +hypot +inet_network +ioctl +isalnum +isalpha +isatty +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +isxdigit +j0 +j1 +jn +kill +labs +ldexp +ldiv +localtime +log +log10 +longjmp +lseek +malloc +mblen +memchr +memcmp +memcpy +memmove +memset +mkdir +mktime +mmap +modf +mprotect +msync +munmap +open +opendir +perror +pipe +poll +pow +printf +putchar +putenv +puts +qsort +raise +rand +read +readdir +realloc +remove +rename +rmdir +select +setbuf +setlocale +setsid +settimeofday +setvbuf +shmat +shmctl +shmdt +shmget +sigaction +sigaddset +sigaltstack +sigemptyset +signal +sigprocmask +sin +sin +sinh +sleep +snprintf +sprintf +sqrt +srand +sscanf +statfs +strcasecmp +strcat +strchr +strcmp +strcoll +strcpy +strcspn +strdup +strerror +strftime +strlen +strncasecmp +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtod +strtok +strtol +strtoul +strxfrm +sysi86 +system +tan +tanh +tcflush +tcgetattr +tcsetattr +tempnam +time +times +tmpnam +tolower +toupper +towlower +towupper +unlink +usleep +utime +vfprintf +vsprintf +wait4 +write +y0 +y1 +yn diff --git a/tools/winapi_check/nativeapi.pm b/tools/winapi_check/nativeapi.pm new file mode 100644 index 00000000000..136689d4e3a --- /dev/null +++ b/tools/winapi_check/nativeapi.pm @@ -0,0 +1,38 @@ +package nativeapi; + +use strict; + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = {}; + bless ($self, $class); + + my $functions = \%{$self->{FUNCTIONS}}; + + my $file = shift; + + open(IN, "< $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; + } + close(IN); + + return $self; +} + +sub is_function { + my $self = shift; + my $functions = \%{$self->{FUNCTIONS}}; + + my $name = shift; + + return $$functions{$name}; +} + +1; diff --git a/tools/winapi_check/parser.pm b/tools/winapi_check/parser.pm new file mode 100644 index 00000000000..537ef70f44b --- /dev/null +++ b/tools/winapi_check/parser.pm @@ -0,0 +1,184 @@ +package parser; + +BEGIN { + use Exporter (); + use vars qw(@ISA @EXPORT); + + @ISA = qw(Exporter); + @EXPORT = qw(&init + &transact &commit &rollback &token + &dump_state + &either &filter &many &many1 &separate &separate1 &sequence); +} + +my @stack; +my $current; +my $next; + +sub init { + @stack = (); + $current = []; + $next = shift; + + @$next = grep { + $_->{type} !~ /^comment|preprocessor$/; + } @$next; +} + +sub dump_state { + print "stack: [\n"; + for my $tokens (@stack) { + print " [\n"; + for my $token (@$tokens) { + print " " . $token->{type} . ": " . $token->{data} . "\n"; + } + print " ]\n"; + } + print "]\n"; + print "current: [\n"; + for my $token (@$current) { + print " " . $token->{type} . ": " . $token->{data} . "\n"; + } + print "]\n"; + print "next: [\n"; + for my $token (@$next) { + print " " . $token->{type} . ": " . $token->{data} . "\n"; + } + print "]\n"; +} + +sub token { + my $token = shift @$next; + push @$current, $token; + return $token; +}; + +sub transact { + push @stack, $current; + $current = []; +} + +sub commit { + my $oldcurrent = $current; + $current = pop @stack; + push @$current, @$oldcurrent; +} + +sub rollback { + unshift @$next, @$current; + $current = pop @stack; +} + +sub filter { + my $parser = shift; + my $filter = shift; + + transact; + my $r1 = &$parser; + if(defined($r1)) { + my $r2 = &$filter($r1); + if($r2) { + commit; + return $r1; + } else { + rollback; + return undef; + } + } else { + rollback; + return undef; + } +} + +sub either { + for my $parser (@_) { + transact; + my $r = &$parser; + if(defined($r)) { + commit; + return $r; + } else { + rollback; + } + } + return undef; +} + +sub sequence { + transact; + my $rs = []; + for my $parser (@_) { + my $r = &$parser; + if(defined($r)) { + push @$rs, $r; + } else { + rollback; + return undef; + } + } + commit; + return $rs; +} + +sub separate { + my $parser = shift; + my $separator = shift; + my $rs = []; + while(1) { + my $r = &$parser; + if(defined($r)) { + push @$rs, $r; + } else { + last; + } + my $s = &$separator; + if(!defined($r)) { + last; + } + + } + return $rs; +} + +sub separate1 { + my $parser = shift; + my $separator = shift; + transact; + my $rs = separate($parser,$separator); + if($#$rs != -1) { + commit; + return $rs; + } else { + rollback; + return undef; + } +} + +sub many { + my $parser = shift; + my $rs = []; + while(1) { + my $r = &$parser; + if(defined($r)) { + push @$rs, $r; + } else { + last; + } + } + return $rs; +} + +sub many1 { + my $parser = shift; + transact; + my $rs = many($parser); + if($#$rs != -1) { + commit; + return $rs; + } else { + rollback; + return undef; + } +} + +1; diff --git a/tools/winapi_check/win16api.dat b/tools/winapi_check/win16api.dat new file mode 100644 index 00000000000..4a317829f01 --- /dev/null +++ b/tools/winapi_check/win16api.dat @@ -0,0 +1,348 @@ +%long + +COLORREF +DWORD +FOURCC +HCONV +HCONVLIST +HDDEDATA +HHOOK +HKEY +HRESULT +HSZ +LCID +LCTYPE +LHCLIENTDOC +LHSERVER +LHSERVERDOC +LONG +LPARAM +LRESULT +POINT16 +ULONG + +%longlong + +LARGE_INTEGER + +%ptr + +ACMDRIVERENUMCB16 +ACMFILTERENUMCB16 +ACMFILTERTAGENUMCB16 +ACMFORMATENUMCB16 +ACMFORMATTAGENUMCB16 +BITMAP16 * +BITMAPINFO * +BITMAPINFOHEADER * +BOOL16 * +BSTR16 * +CLASSENTRY * +CLSID * +COLORREF * +CONTEXT86 * +CURSORICONINFO * +DEVMODEA * +DOCINFO16 * +DWORD * +FARPROC * +FARPROC16 * +FILETIME * +GLOBALENTRY * +GLOBALINFO * +GUID * +HANDLE * +HANDLETABLE16 * +HHOOK * +HICON16 * +HINSTANCE16 * +HMIDIIN16 * +HMIDIOUT16 * +HMIDISTRM16 * +HPCSTR +HPSTR +HTASK16 * +HWAVEIN16 * +HWAVEOUT16 * +IID * +IMalloc16 * +INT16 * +INTERFACEDATA * +IStorage16 * +IStorage16 ** +IStream16 * +IStream16 ** +ITypeInfo ** +IUnknown * +LHCLIENTDOC * +LHSERVERDOC * +LOCAL32ENTRY * +LOCAL32INFO * +LOCALENTRY * +LOCALINFO * +LOGBRUSH16 * +LOGFONT16 * +LOGPALETTE * +LOGPEN16 * +LPABC16 +LPACMDRIVERDETAILS16 +LPACMFILTERCHOOSE16 +LPACMFILTERDETAILS16 +LPACMFILTERTAGDETAILS16 +LPACMFORMATCHOOSE16 +LPACMFORMATDETAILS16 +LPACMFORMATTAGDETAILS16 +LPACMSTREAMHEADER16 +LPAUXCAPS16 +LPBSTR16 +LPBYTE +LPCATCHBUF +LPCHOOSECOLOR16 +LPCHOOSEFONT16 +LPCLSID +LPCOMSTAT16 +LPCONVCONTEXT16 +LPCONVINFO16 +LPCURSORINFO +LPCVOID +LPDCB16 +LPDEVMODEA +LPDRIVERINFOSTRUCT16 +LPDWORD +LPENUMLOGFONT16 +LPFILETIME +LPFONTINFO16 +LPGLYPHMETRICS16 +LPHACMDRIVER16 +LPHACMDRIVERID16 +LPHACMSTREAM16 +LPHANDLE +LPHKEY +LPHMIXER16 +LPICONINFO16 +LPINT16 +LPJOYCAPS16 +LPJOYINFO16 +LPKERNINGPAIR16 +LPLOGFONT16 +LPMALLOC16 * +LPMEMORY_BASIC_INFORMATION +LPMESSAGEFILTER +LPMESSAGEFILTER * +LPMIDIHDR16 +LPMIDIINCAPS16 +LPMIDIOUTCAPS16 +LPMIXERCAPS16 +LPMIXERCONTROLDETAILS16 +LPMIXERLINE16 +LPMIXERLINECONTROLS16 +LPMMCKINFO +LPMMIOPROC16 +LPMMTIME16 +LPMONIKER * +LPMSG16 +LPMSG16_32 +LPMSGBOXPARAMS16 +LPNEWTEXTMETRIC16 +LPOFSTRUCT +LPOLECLIENT +LPOLEOBJECT +LPOLEOBJECT * +LPOLESERVERDOC +LPOLESTR16 * +LPDROPTARGET +LPOUTLINETEXTMETRIC16 +LPPAINTSTRUCT16 +LPPALETTEENTRY +LPPDEVICE +LPPOINT16 +LPQUEUESTRUCT16 * +LPRASTERIZER_STATUS +LPRECT16 +LPRGNDATA +LPRUNNINGOBJECTTABLE * +LPSCROLLINFO +LPSIZE16 +LPSTORAGE16 +LPTEXTXFORM16 +LPTIMECAPS16 +LPUINT16 +LPUNKNOWN +LPVOID +LPVOID * +LPWAVEFILTER +LPWAVEFORMATEX +LPWAVEINCAPS16 +LPWAVEOUTCAPS16 +LPWIN32SINFO +LPWORD +LPWSADATA +MAT2 * +MEMMANINFO * +MENUITEMINFO16 * +METARECORD * +MIDIHDR16 * +MMCKINFO * +MMIOINFO16 * +MODULEENTRY * +MSG16 * +MSG32_16 * +OFSTRUCT * +OSVERSIONINFO16 * +PAINTSTRUCT16 * +PALETTEENTRY * +POINT16 * +RECT16 * +REFCLSID +REFGUID +REFIID +RGBQUAD * +SCROLLINFO * +SECURITY_ATTRIBUTES * +SEGINFO * +SEGPTR * +SNB16 +STACKTRACEENTRY * +STATSTG16 * +SYSHEAPINFO * +SYSLEVEL * +TASKENTRY * +TEXTMETRIC16 * +THUNKLET * +TIMERINFO * +UINT16 * +ULARGE_INTEGER * +ULONG * +VOID * +WAVEHDR * +WIN32_FIND_DATAA * +WINDEBUGINFO * +WINDOWPLACEMENT16 * +WNDCLASS16 * +WNDCLASSEX16 * +WORD * +char * +struct ThunkDataCommon * +struct Win87EmInfoStruct * +struct sockaddr * +struct tagCURSORICONINFO * +struct timeval * +void * +ws_fd_set16 * + +%s_word + +INT16 + +%segptr + +DLGPROC16 +FARPROC16 +FONTENUMPROC16 +FONTENUMPROCEX16 +GOBJENUMPROC16 +GRAYSTRINGPROC16 +HOOKPROC16 +LINEDDAPROC16 +LPTIMECALLBACK16 +MFENUMPROC16 +PROPENUMPROC16 +SEGPTR +TIMERPROC16 +WNDENUMPROC16 +WNDPROC16 + +%segstr + +BSTR16 + +%str + +LPCOLESTR16 +LPCSTR +LPCWSTR +LPSTR +LPOLESTR16 + +%unknown + +struct in_addr + +%void + +void +VOID + +%word + +ATOM +BOOL16 +BYTE +CHAR +HACCEL16 +HACMDRIVER16 +HACMDRIVERID16 +HACMOBJ16 +HACMSTREAM16 +HANDLE16 +HBITMAP16 +HBRUSH16 +HCURSOR16 +HDC16 +HDROP16 +HDRVR16 +HDWP16 +HFILE16 +HFONT16 +HGDIOBJ16 +HGLOBAL16 +HICON16 +HINSTANCE16 +HLOCAL16 +HMENU16 +HMETAFILE16 +HMIDIIN16 +HMIDIOUT16 +HMIDISTRM16 +HMIXER16 +HMIXEROBJ16 +HMMIO16 +HMODULE16 +HPALETTE16 +HPEN16 +HPJOB16 +HPQ16 +HQUEUE16 +HRGN16 +HRSRC16 +HTASK16 +HWAVEIN16 +HWAVEOUT16 +HWND16 +LANGID +MMRESULT16 +OLESTATUS +SOCKET16 +UINT16 +WING_DITHER_TYPE +WORD +WPARAM16 + +%unknown --forbidden + +BOOL +FARPROC +HANDLE +HINSTANCE +HMODULE +HWND +INT +LPOLESTR +UINT +YIELDPROC +int +long +short +u_long +u_short +unsigned diff --git a/tools/winapi_check/win32api.dat b/tools/winapi_check/win32api.dat new file mode 100644 index 00000000000..f553d1253a2 --- /dev/null +++ b/tools/winapi_check/win32api.dat @@ -0,0 +1,785 @@ +%double + +CY +double + +%long + +ACCESS_MASK +ATOM +BOOL +BOOLEAN +BYTE +CALID +CALTYPE +CHAR +CLIPFORMAT +COLORREF +COORD +DATE +DIGEST_HANDLE +DPAENUMPROC +DWORD +FILE_INFORMATION_CLASS +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 +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 +LANGID +LCID +LCTYPE +LHCLIENTDOC +LHSERVER +LHSERVERDOC +LONG +LPARAM +LRESULT +MMRESULT +NTSTATUS +OBJECT_INFORMATION_CLASS +OLECLIPFORMAT +OLEOPT_RENDER +OLESTATUS +OLE_SERVER_USE +OUT +PHANDLE +PHPROVIDER +PIO_APC_ROUTINE +PLSA_HANDLE +PLSA_OBJECT_ATTRIBUTES +PLSA_UNICODE_STRING +POBJDIR_INFORMATION +PROCESSINFOCLASS +PTIME_FIELDS +PTOKEN_PRIVILEGES +REGSAM +SC_HANDLE +SECTION_INHERIT +SECURITY_IMPERSONATION_LEVEL +SECURITY_INFORMATION +SEGPTR +SERVICE_STATUS_HANDLE +SHORT +SOCKET +SYSKIND +SYSTEM_INFORMATION_CLASS +THREADINFOCLASS +TIMER_TYPE +TOKEN_INFORMATION_CLASS +TOKEN_TYPE +UINT +ULONG +ULONG_PTR +USHORT +VARIANT_BOOL +VARTYPE +WCHAR +WORD +WOW_HANDLE_TYPE +WPARAM +clock_t +enum NOTIFYTYPE +time_t + +%longlong + +LARGE_INTEGER +POINT + +%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 * +CRITICAL_SECTION * +CRTDLL_FILE * +CY * +DATE * +DATEFMT_ENUMPROCA +DATEFMT_ENUMPROCW +DEVMODEA * +DEVMODEW * +DIGEST_FUNCTION +DLGPROC +DLLVERSIONINFO * +DOCINFOA * +DOCINFOW * +DPALOADPROC +DRAWSTATEPROC +DSAENUMPROC +DWORD * +ENHMETARECORD * +ENHMFENUMPROC +ENUMRESLANGPROCA +ENUMRESLANGPROCW +ENUMRESNAMEPROCA +ENUMRESNAMEPROCW +ENUMRESTYPEPROCA +ENUMRESTYPEPROCW +EXCEPTION_RECORD * +FARPROC +FARPROC * +FILETIME * +FLOAT * +FONTENUMPROCA +FONTENUMPROCEXA +FONTENUMPROCEXW +FONTENUMPROCW +GCP_RESULTSA * +GCP_RESULTSW * +GOBJENUMPROC +GRAYSTRINGPROC +GUID * +HANDLE * +HANDLER_ROUTINE * +HANDLETABLE * +HCRYPTPROV * +HDPA +HDPA * +HGLOBAL * +HICON * +HIMAGELIST +HIMAGELIST * +HKL * +HMENU * +HMIDIIN * +HMIDIOUT * +HMIDISTRM * +HMRU +HOOKPROC +HPCSTR +HPSTR +HWAVEIN * +HWAVEOUT * +HWND * +ICINFO * +IDSTRUCT * +IDataObject * +IDataObject ** +IDropSource * +IDropTarget * +ILockBytes * +IMAGEINFO * +IMAGELISTDRAWPARAMS * +INPUT_RECORD * +INT * +IPersistStream * +IShellFolder ** +IStorage * +IStorage ** +IStream * +ITypeLib * +ITypeLib ** +IUnknown * +LHCLIENTDOC * +LHSERVER * +LHSERVERDOC * +LINECALLBACK +LINEDDAPROC +LOCALE_ENUMPROCA +LOCALE_ENUMPROCW +LOGBRUSH * +LOGFONTA * +LOGFONTW * +LOGPALETTE * +LOGPEN * +LONG * +LPABC +LPABCFLOAT +LPACCEL +LPAUTHDLGSTRUCTA +LPAUXCAPSA +LPAUXCAPSW +LPAVIFILEINFOA +LPAVIFILEINFOW +LPBC * +LPBITMAPINFOHEADER +LPBOOL +LPBROWSEINFOA +LPBSTR +LPBYTE +LPCANDIDATEFORM +LPCANDIDATELIST +LPCHARSETINFO +LPCHAR_INFO +LPCHOOSECOLORA +LPCHOOSECOLORW +LPCHOOSEFONTA +LPCHOOSEFONTW +LPCITEMIDLIST +LPCITEMIDLIST * +LPCLSID +LPCMENUINFO +LPCOLDTBBUTTON +LPCOLORADJUSTMENT +LPCOLORMAP +LPCOMMTIMEOUTS +LPCOMPOSITIONFORM +LPCOMSTAT +LPCONNECTDLGSTRUCTA +LPCONNECTDLGSTRUCTW +LPCONSOLE_CURSOR_INFO +LPCONSOLE_SCREEN_BUFFER_INFO +LPCONVCONTEXT +LPCONVINFO +LPCPINFO +LPCPROPSHEETHEADERA +LPCPROPSHEETHEADERW +LPCPROPSHEETPAGEA +LPCPROPSHEETPAGEW +LPCSTR * +LPCTBBUTTON +LPCVOID +LPCWSTR * +LPDATAADVISEHOLDER * +LPDATAOBJECT +LPDCB +LPDDENUMCALLBACKA +LPDDENUMCALLBACKEXA +LPDDENUMCALLBACKEXW +LPDDENUMCALLBACKW +LPDEBUG_EVENT +LPDEVMODEA +LPDEVMODEW +LPDIRECTDRAW * +LPDIRECTDRAWCLIPPER * +LPDIRECTPLAYLOBBY * +LPDIRECTPLAYLOBBYA * +LPDIRECTSOUND * +LPDISCDLGSTRUCTA +LPDISCDLGSTRUCTW +LPDPENUMDPCALLBACKA +LPDPENUMDPCALLBACKW +LPDRAWITEMSTRUCT +LPDRAWTEXTPARAMS +LPDROPTARGET +LPDSENUMCALLBACKA +LPDWORD +LPENHMETAHEADER +LPENUMFORMATETC * +LPENUMOLEVERB * +LPENUM_SERVICE_STATUSA +LPFILETIME +LPFINDREPLACEA +LPFINDREPLACEW +LPFNCREATEINSTANCE +LPFNFMCALLBACK +LPFONTDESC +LPFONTSIGNATURE +LPFORMATETC +LPGLYPHMETRICS +LPGUID +LPHANDLE +LPHANDLER_FUNCTION +LPHANDLETABLE +LPHCALL +LPHKEY +LPHLINE +LPHLINEAPP +LPHMIXER +LPHPHONE +LPHPHONEAPP +LPICONINFO +LPINITCOMMONCONTROLSEX +LPINPUT_RECORD +LPINT +LPITEMIDLIST * +LPITEMIDLIST +LPJOYCAPSA +LPJOYCAPSW +LPJOYINFO +LPJOYINFOEX +LPKERNINGPAIR +LPLDT_ENTRY +LPLINEADDRESSCAPS +LPLINEADDRESSSTATUS +LPLINECALLINFO +LPLINECALLLIST +LPLINECALLPARAMS +LPLINECALLSTATUS +LPLINECOUNTRYLIST +LPLINEDEVCAPS +LPLINEDEVSTATUS +LPLINEDIALPARAMS +LPLINEEXTENSIONID +LPLINEFORWARDLIST +LPLINEGENERATETONE +LPLINEMEDIACONTROLCALLSTATE +LPLINEMEDIACONTROLDIGIT +LPLINEMEDIACONTROLMEDIA +LPLINEMEDIACONTROLTONE +LPLINEMONITORTONE +LPLINEPROVIDERLIST +LPLINETRANSLATECAPS +LPLINETRANSLATEOUTPUT +LPLOCKBYTES * +LPLOGFONTA +LPLOGFONTW +LPLONG +LPMALLOC * +LPMEASUREITEMSTRUCT +LPMEMORYSTATUS +LPMEMORY_BASIC_INFORMATION +LPMENUINFO +LPMENUITEMINFOA +LPMENUITEMINFOW +LPMESSAGEFILTER +LPMESSAGEFILTER * +LPMIDIHDR +LPMIDIINCAPSA +LPMIDIINCAPSW +LPMIDIOUTCAPSA +LPMIDIOUTCAPSW +LPMIXERCAPSA +LPMIXERCAPSW +LPMIXERCONTROLDETAILS +LPMIXERLINEA +LPMIXERLINECONTROLSA +LPMIXERLINECONTROLSW +LPMIXERLINEW +LPMMCKINFO +LPMMIOPROC +LPMMTIME +LPMODULEENTRY +LPMONIKER +LPMONIKER * +LPMONITORINFO +LPMRUINFO +LPMSG +LPMSGBOXPARAMSA +LPMSGBOXPARAMSW +LPNETCONNECTINFOSTRUCT +LPNETINFOSTRUCT +LPNETRESOURCEA +LPNETRESOURCEW +LPNMHDR +LPOFSTRUCT +LPOLEADVISEHOLDER * +LPOLECLIENT +LPOLECLIENTSITE +LPOLEINPLACEACTIVEOBJECT +LPOLEINPLACEFRAME +LPOLEINPLACEFRAMEINFO +LPOLEMENUGROUPWIDTHS +LPOLEOBJECT +LPOLEOBJECT * +LPOLESERVER +LPOLESERVERDOC +LPOLESTR +LPOLESTR * +LPOLEUIBUSYA +LPOLEUIBUSYW +LPOLEUICHANGEICONA +LPOLEUICHANGEICONW +LPOLEUICHANGESOURCEA +LPOLEUICHANGESOURCEW +LPOLEUICONVERTA +LPOLEUICONVERTW +LPOLEUIEDITLINKSA +LPOLEUIEDITLINKSW +LPOLEUIINSERTOBJECTA +LPOLEUIINSERTOBJECTW +LPOLEUILINKCONTAINERA +LPOLEUIOBJECTPROPSA +LPOLEUIOBJECTPROPSW +LPOLEUIPASTESPECIALA +LPOLEUIPASTESPECIALW +LPOPENFILENAMEA +LPOPENFILENAMEW +LPOUTLINETEXTMETRICA +LPOUTLINETEXTMETRICW +LPOVERLAPPED +LPOVERLAPPED_COMPLETION_ROUTINE +LPPAGESETUPDLGA +LPPALETTEENTRY +LPPERSISTSTORAGE +LPPHONEBUTTONINFO +LPPHONECAPS +LPPHONEEXTENSIONID +LPPHONESTATUS +LPPIXELFORMATDESCRIPTOR +LPPOINT +LPPRINTDLGA +LPPRINTDLGW +LPPRINTER_DEFAULTSA +LPPRINTER_DEFAULTSW +LPPROCESSENTRY +LPPROCESS_HEAP_ENTRY * +LPPROCESS_INFORMATION +LPPROGRESS_ROUTINE +LPRASCONNA +LPRASTERIZER_STATUS +LPRECT +LPRGNDATA +LPRTL_RWLOCK +LPRUNNINGOBJECTTABLE * +LPSCROLLINFO +LPSECURITY_ATTRIBUTES +LPSERVICE_STATUS +LPSERVICE_TABLE_ENTRYA +LPSERVICE_TABLE_ENTRYW +LPSHELLEXECUTEINFOA +LPSHELLEXECUTEINFOW +LPSHELLFLAGSTATE +LPSHELLFOLDER +LPSHELLVIEWDATA +LPSHFILEOPSTRUCTA +LPSHFILEOPSTRUCTW +LPSIZE +LPSMALL_RECT +LPSRB +LPSTARTUPINFOA +LPSTARTUPINFOW +LPSTORAGE +LPSTR * +LPSTR ** +LPSTREAM +LPSTREAM * +LPSTRRET +LPSTYLEBUFA +LPSTYLEBUFW +LPSYSTEMTIME +LPSYSTEM_INFO +LPSYSTEM_POWER_STATUS +LPTHREAD_START_ROUTINE +LPTIMECALLBACK +LPTIMECAPS +LPTIME_ZONE_INFORMATION +LPTOP_LEVEL_EXCEPTION_FILTER +LPTPMPARAMS +LPUINT +LPUNKNOWN +LPUNKNOWN * +LPVARSTRING +LPVOID +LPVOID * +LPWAVEFORMATEX +LPWAVEINCAPSA +LPWAVEINCAPSW +LPWAVEOUTCAPSA +LPWAVEOUTCAPSW +LPWORD +LPWSADATA +LPWSTR * +LPXFORM +MAT2 * +MENUITEMINFOA * +MENUITEMINFOW * +METARECORD * +MFENUMPROC +MIDIHDR * +MMCKINFO * +MMIOINFO * +MONITORENUMPROC +MSG * +MULTI_QI * +NOTIFYCALLBACK +NUMBERFMTA * +NUMBERFMTW * +OFSTRUCT * +OSVERSIONINFOA * +OSVERSIONINFOW * +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 +PCHAR * +PCONTEXT +PDWORD +PENUMLOADED_MODULES_CALLBACK +PEXCEPTION_FRAME +PEXCEPTION_FRAME * +PEXCEPTION_POINTERS +PEXCEPTION_RECORD +PFLOAT +PFNCALLBACK +PFNDPACOMPARE +PFNDPAMERGE +PFUNCTION_TABLE_ACCESS_ROUTINE +PGENERIC_MAPPING +PGETFRAME +PGET_MODULE_BASE_ROUTINE +PHACMDRIVER +PHACMDRIVERID +PHACMSTREAM +PHONECALLBACK +PIMAGEHLP_MODULE +PIMAGEHLP_STATUS_ROUTINE +PIMAGEHLP_SYMBOL +PIMAGE_DEBUG_INFORMATION +PIMAGE_LOAD_CONFIG_DIRECTORY +PIMAGE_NT_HEADERS +PIMAGE_SECTION_HEADER +PIMAGE_SECTION_HEADER * +PIO_STATUS_BLOCK +PIXELFORMATDESCRIPTOR * +PLARGE_INTEGER +PLOADED_IMAGE +PLONG +PLUID +PNOTIFYICONDATAA +POBJECT_ATTRIBUTES +POINT * +PPRIVILEGE_SET +PREAD_PROCESS_MEMORY_ROUTINE +PRTL_HEAP_DEFINITION +PROPENUMPROCA +PROPENUMPROCEXA +PROPENUMPROCEXW +PROPENUMPROCW +PSECURITY_DESCRIPTOR +PSECURITY_DESCRIPTOR_CONTROL +PSECURITY_QUALITY_OF_SERVICE +PSID +PSID * +PSID_IDENTIFIER_AUTHORITY +PSID_NAME_USE +PSTACKFRAME +PSTRING +PSYMBOL_REGISTERED_CALLBACK +PSYM_ENUMMODULES_CALLBACK +PSYM_ENUMSYMBOLS_CALLBACK +PTIMERAPCROUTINE +PTRANSLATE_ADDRESS_ROUTINE +PUCHAR +PULARGE_INTEGER +PULONG +PUNICODE_STRING +PVOID +PVOID * +PWAVEFILTER +PWAVEFORMATEX +PWIN_CERTIFICATE +RECT * +REFCLSID +REFGUID +REFIID +REGISTERWORDENUMPROCA +REGISTERWORDENUMPROCW +RGBQUAD * +RGNDATA * +SAFEARRAY * +SAFEARRAY ** +SAFEARRAYBOUND * +SCROLLINFO * +SECURITY_ATTRIBUTES * +SECURITY_DESCRIPTOR * +SECURITY_INFORMATION * +SHFILEINFOA * +SHFILEINFOW * +SNB +STGMEDIUM * +SYSLEVEL * +SYSLEVEL ** +SYSTEMTIME * +TEXTMETRICA * +TEXTMETRICW * +TIMEFMT_ENUMPROCA +TIMEFMT_ENUMPROCW +TIMERPROC +UINT * +ULONG * +USHORT * +VARIANT * +VARIANTARG * +VARIANT_BOOL * +VOID * +VOID ** +WAVEHDR * +WCHAR * +WIN32_FIND_DATAA * +WIN32_FIND_DATAW * +WINDOWPLACEMENT * +WNDCLASSA * +WNDCLASSEXA * +WNDCLASSEXW * +WNDCLASSW * +WNDENUMPROC +WNDPROC +WORD * +XFORM * +YIELDPROC +_INITTERMFUN * +char * +double * +jmp_buf +short * +struct _TEB * +struct ThunkDataCommon * +struct find_t * +struct sockaddr * +struct stat * +struct timeval * +struct win_stat * +struct WIN_hostent * +struct WIN_protoent * +struct WIN_servent * +time_t * +va_list +void * +void ** +ws_fd_set32 * + +%str + +LPCSTR +LPSTR +OLECHAR * + +%unknown + +new_handler_type +sig_handler_type +struct in_addr + +%void + +void +VOID + +%wstr + +BSTR +LPCOLESTR +LPCWSTR +LPWSTR + +%long # --forbidden + +BOOL16 +FARPROC16 +HTASK16 +HGLOBAL16 +HINSTANCE16 +HMMIO16 +HMODULE16 +LPOLESTR16 +UINT16 +SOCKET16 +int +long +short +u_long +u_short +unsigned diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm new file mode 100644 index 00000000000..6b48905574e --- /dev/null +++ b/tools/winapi_check/winapi.pm @@ -0,0 +1,318 @@ +package winapi; + +use strict; + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = {}; + bless ($self, $class); + + my $allowed_kind = \%{$self->{ALLOWED_KIND}}; + my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; + my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}}; + my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; + + $self->{NAME} = shift; + my $file = shift; + + my @modules; + my $kind; + my $forbidden = 0; + + open(IN, "< $file") || die "$file: $!\n"; + $/ = "\n"; + while() { + s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line + s/^(.*?)\s*#.*$/$1/; # remove comments + /^$/ && next; # skip empty lines + + if(s/^%(\S+)\s*//) { + $kind = $1; + @modules = (); + $forbidden = 0; + + $$allowed_kind{$kind} = 1; + if(/^--module=(\S*)/) { + @modules = split(/,/, $1); + } elsif(/^--forbidden/) { + $forbidden = 1; + } + } elsif(defined($kind)) { + my $type = $_; + if(!$forbidden) { + for my $module (@modules) { + $$allowed_modules_limited{$type} = 1; + $$allowed_modules{$type}{$module} = 1; + } + } else { + $$allowed_modules_limited{$type} = 1; + } + $$translate_argument{$type} = $kind; + } else { + print "$file: file must begin with % statement\n"; + exit 1; + } + } + close(IN); + + return $self; +} + +sub get_spec_file_type { + my $proto = shift; + my $class = ref($proto) || $proto; + + my $file = shift; + + my $type; + + open(IN, "< $file") || die "$file: $!\n"; + $/ = "\n"; + while() { + if(/^type\s*(\w+)/) { + $type = $1; + last; + } + } + close(IN); + + return $type; +} + +sub read_spec_files { + my $proto = shift; + my $class = ref($proto) || $proto; + + my $win16api = shift; + my $win32api = shift; + + foreach my $file (split(/\n/, `find . -name \\*.spec`)) { + my $type = 'winapi'->get_spec_file_type($file); + if($type eq "win16") { + $win16api->parse_spec_file($file); + } elsif($type eq "win32") { + $win32api->parse_spec_file($file); + } + } +} + +sub parse_spec_file { + my $self = shift; + 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 $type; + my $module; + + open(IN, "< $file") || die "$file: $!\n"; + $/ = "\n"; + my $header = 1; + my $lookahead = 0; + while($lookahead || defined($_ = )) { + $lookahead = 0; + s/^\s*(.*?)\s*$/$1/; + s/^(.*?)\s*#.*$/$1/; + /^$/ && next; + + if($header) { + if(/^name\s*(\S*)/) { $module = $1; } + if(/^\d+/) { $header = 0 }; + 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; + + # 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_stub{$external_name} = 1; + $$function_module{$external_name} = $module; + } elsif(/^\d+\s+(equate|long|word|extern|forward)/) { + # ignore + } else { + my $next_line = ; + if($next_line =~ /^\d/) { + die "$file: $.: syntax error: '$_'\n"; + } else { + $_ .= $next_line; + $lookahead = 1; + } + } + } + close(IN); +} + +sub name { + my $self = shift; + return $self->{NAME}; +} + +sub is_allowed_kind { + my $self = shift; + my $allowed_kind = \%{$self->{ALLOWED_KIND}}; + + my $kind = shift; + if(defined($kind)) { + return $$allowed_kind{$kind}; + } else { + return 0; + } +} + +sub allowed_type_in_module { + my $self = shift; + my $allowed_modules = \%{$self->{ALLOWED_MODULES}}; + my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}}; + + my $type = shift; + my $module = shift; + + return !$$allowed_modules_limited{$type} || $$allowed_modules{$type}{$module}; +} + +sub translate_argument { + my $self = shift; + my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; + + my $argument = shift; + + return $$translate_argument{$argument}; +} + +sub all_declared_types { + my $self = shift; + my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; + + return sort(keys(%$translate_argument)); +} + +sub found_type { + my $self = shift; + my $type_found = \%{$self->{TYPE_FOUND}}; + + my $name = shift; + + $$type_found{$name}++; +} + +sub type_found { + my $self = shift; + my $type_found= \%{$self->{TYPE_FOUND}}; + + my $name = shift; + + return $$type_found{$name}; +} + +sub all_functions { + my $self = shift; + my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}}; + + return sort(keys(%$function_calling_convention)); +} + +sub all_functions_found { + my $self = shift; + my $function_found = \$self->{FUNCTION_FOUND}; + + return sort(keys(%$function_found)); +} + +sub function_calling_convention { + my $self = shift; + my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}}; + + my $name = shift; + + return $$function_calling_convention{$name}; +} + +sub is_function { + my $self = shift; + my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}}; + + my $name = shift; + + return $$function_calling_convention{$name}; +} + +sub is_shared_function { + my $self = shift; + my $function_shared = \%{$self->{FUNCTION_SHARED}}; + + my $name = shift; + + return $$function_shared{$name}; +} + +sub found_shared_function { + my $self = shift; + my $function_shared = \%{$self->{FUNCTION_SHARED}}; + + my $name = shift; + + $$function_shared{$name} = 1; +} + +sub function_arguments { + my $self = shift; + my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}}; + + my $name = shift; + + return $$function_arguments{$name}; +} + +sub function_module { + my $self = shift; + my $function_module = \%{$self->{FUNCTION_MODULE}}; + + my $name = shift; + + if($self->is_function($name)) { + return $$function_module{$name}; + } else { + return undef; + } +} + +sub function_stub { + my $self = shift; + my $function_stub = \%{$self->{FUNCTION_STUB}}; + + my $name = shift; + + return $$function_stub{$name}; +} + +sub found_function { + my $self = shift; + my $function_found = \%{$self->{FUNCTION_FOUND}}; + + my $name = shift; + + $$function_found{$name}++; +} + +sub function_found { + my $self = shift; + my $function_found = \%{$self->{FUNCTION_FOUND}}; + + my $name = shift; + + return $$function_found{$name}; +} + +1; diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check new file mode 100755 index 00000000000..1323685b32e --- /dev/null +++ b/tools/winapi_check/winapi_check @@ -0,0 +1,118 @@ +#!/usr/bin/perl -w + +# Copyright 1999 Patrik Stridvall + +use strict; + +BEGIN { + require "tools/winapi_check/winapi.pm"; + require "tools/winapi_check/nativeapi.pm"; + require "tools/winapi_check/winapi_local.pm"; + require "tools/winapi_check/winapi_global.pm"; + require "tools/winapi_check/winapi_options.pm"; + require "tools/winapi_check/winapi_parser.pm"; + + import winapi; + import nativeapi; + import winapi_local; + import winapi_global; + import winapi_options; + import winapi_parser; +} + +my $options = winapi_options->new(\@ARGV); +if($options->help) { + $options->show_help; + exit; +} + +my $win16api = 'winapi'->new("win16", "tools/winapi_check/win16api.dat"); +my $win32api = 'winapi'->new("win32", "tools/winapi_check/win32api.dat"); +'winapi'->read_spec_files($win16api, $win32api); + +my $nativeapi = 'nativeapi'->new("tools/winapi_check/nativeapi.dat"); + +for my $name ($win32api->all_functions) { + my $module16 = $win16api->function_module($name); + my $module32 = $win32api->function_module($name); + + if(defined($module16)) { + $win16api->found_shared_function($name); + $win32api->found_shared_function($name); + + if($options->shared) { + print "*.spec: $name: is shared between $module16 (Win16) and $module32 (Win32)\n"; + } + } +} + +foreach my $file ($options->files) { + my $found_function = sub { + my $return_type = shift; + my $calling_convention = shift; + my $name = shift; + my $refarguments = shift; + my @arguments = @$refarguments; + + if($options->global) { + $win16api->found_type($return_type) if $options->win16; + $win32api->found_type($return_type) if $options->win32; + for my $argument (@arguments) { + $win16api->found_type($argument) if $options->win16; + $win32api->found_type($argument) if $options->win32; + } + + $win16api->found_function($name) if $options->win16; + $win32api->found_function($name) if $options->win32; + } + + if($options->local) { + my $module16 = $win16api->function_module($name); + my $module32 = $win32api->function_module($name); + my $output = sub { + my $module = shift; + return sub { + my $msg = shift; + print "$file: $module: $return_type $calling_convention $name(" . join(",", @arguments) . "): $msg\n"; + } + }; + my $output16 = &$output($module16); + my $output32 = &$output($module32); + + if($options->argument) { + if($options->win16 && $options->report_module($module16)) { + winapi_local::check_arguments $options, $output16, + $return_type, $calling_convention, $name, [@arguments], $win16api; + } + if($options->win32 && $options->report_module($module32)) { + winapi_local::check_arguments $options, $output32, + $return_type, $calling_convention, $name, [@arguments], $win32api; + } + } + if($options->misplaced) { + my $module; + if($file =~ m'^dlls/(.*)/') { + $module = $1; + } + + if($options->win16 && $options->report_module($module16)) { + if(!defined($module) || $module ne $module16) { + &$output16("function misplaced"); + } + } + + if($options->win32 && $options->report_module($module32)) { + if(!defined($module) || $module ne $module32) { + &$output32("function misplaced"); + } + } + } + } + }; + winapi_parser::parse_c_file $options, $file, $found_function; +} + +if($options->global) { + 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 new file mode 100644 index 00000000000..0c4322d4d24 --- /dev/null +++ b/tools/winapi_check/winapi_global.pm @@ -0,0 +1,41 @@ +package winapi_global; + +use strict; + +sub check { + my $options = shift; + my $winapi = shift; + my $nativeapi = shift; + + my $winver = $winapi->name; + + 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($options->declared) { + foreach my $name ($winapi->all_functions) { + if(!$winapi->function_found($name) && !$nativeapi->is_function($name)) { + print "*.c: $winver: $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"; + } + } + } +} + +1; + diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm new file mode 100644 index 00000000000..88126bb9386 --- /dev/null +++ b/tools/winapi_check/winapi_local.pm @@ -0,0 +1,136 @@ +package winapi_local; + +use strict; + +sub check_arguments { + my $options = shift; + my $output = shift; + my $return_type = shift; + my $calling_convention = shift; + my $name = shift; + my $refargument_types = shift; + my @argument_types = @$refargument_types; + my $winapi = shift; + + my $module = $winapi->function_module($name); + + my $forbidden_return_type = 0; + my $implemented_return_kind; + if(!defined($implemented_return_kind = $winapi->translate_argument($return_type))) { + if($return_type ne "") { + &$output("no translation defined: " . $return_type); + } + } elsif(!$winapi->is_allowed_kind($implemented_return_kind) || !$winapi->allowed_type_in_module($return_type,$module)) { + $forbidden_return_type = 1; + if($options->report_argument_forbidden($return_type)) { + &$output("forbidden return type: $return_type ($implemented_return_kind)"); + } + } + + my $segmented = 0; + if($implemented_return_kind =~ /^segptr|segstr$/) { + $segmented = 1; + } + + my $implemented_calling_convention; + if($winapi->name eq "win16") { + if($calling_convention =~ /^__cdecl$/) { + $implemented_calling_convention = "cdecl"; + } elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI$/) { + if($implemented_return_kind =~ /^s_word|word|void$/) { + $implemented_calling_convention = "pascal16"; + } else { + $implemented_calling_convention = "pascal"; + } + } + } elsif($winapi->name eq "win32") { + if($calling_convention =~ /^__cdecl$/) { + $implemented_calling_convention = "cdecl"; + } elsif($calling_convention =~ /^VFWAPIV|WINAPIV$/) { + $implemented_calling_convention = "varargs"; + } elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI$/) { + $implemented_calling_convention = "stdcall"; + } + } + + my $declared_calling_convention = $winapi->function_calling_convention($name); + my @declared_argument_kinds = split(/\s+/, $winapi->function_arguments($name)); + + if($declared_calling_convention =~ /^register|interrupt$/) { + push @declared_argument_kinds, "ptr"; + } + + if($declared_calling_convention =~ /^register|interupt$/ && + (($winapi->name eq "win32" && $implemented_calling_convention eq "stdcall") || + (($winapi->name eq "win16" && $implemented_calling_convention =~ /^pascal/)))) + { + # correct + } elsif($implemented_calling_convention ne $declared_calling_convention && + !($declared_calling_convention =~ /^pascal/ && $forbidden_return_type)) + { + if($options->calling_convention) { + &$output("calling convention mismatch: $implemented_calling_convention != $declared_calling_convention"); + } + } + + if($declared_calling_convention eq "varargs") { + if($#argument_types != -1 && $argument_types[$#argument_types] eq "...") { + pop @argument_types; + } else { + &$output("function not implemented as vararg"); + } + } elsif($#argument_types != -1 && $argument_types[$#argument_types] eq "...") { + &$output("function not declared as vararg"); + } + + 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"; + if(!defined($kind = $winapi->translate_argument($type))) { + &$output("no translation defined: " . $type); + } elsif(!$winapi->is_allowed_kind($kind) || + !$winapi->allowed_type_in_module($type, $module)) { + if($options->report_argument_forbidden($type)) { + &$output("forbidden argument " . ($n + 1) . " type (" . $type . ")"); + } + } + $n++; + $kind; + } @argument_types; + + for my $n (0..$#argument_kinds) { + if(!defined($argument_kinds[$n]) || !defined($declared_argument_kinds[$n])) { next; } + + if($argument_kinds[$n] =~ /^segptr|segstr$/ || + $declared_argument_kinds[$n] =~ /^segptr|segstr$/) + { + $segmented = 1; + } + + if($argument_kinds[$n] ne $declared_argument_kinds[$n]) { + if($options->report_argument_kind($argument_kinds[$n]) || + $options->report_argument_kind($declared_argument_kinds[$n])) + { + &$output("argument " . ($n + 1) . " type mismatch: " . + $argument_types[$n] . " ($argument_kinds[$n]) != " . $declared_argument_kinds[$n]); + } + } + + } + } + + if($segmented && $options->shared_segmented && $winapi->is_shared_function($name)) { + &$output("function using segmented pointers shared between Win16 och Win32"); + } +} + +1; + diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm new file mode 100644 index 00000000000..efadd5b1a15 --- /dev/null +++ b/tools/winapi_check/winapi_options.pm @@ -0,0 +1,272 @@ +package winapi_options; + +use strict; + + +sub parser_comma_list { + my $prefix = shift; + my $value = shift; + if(defined($prefix) && $prefix eq "no") { + return { active => 0, filter => 0, hash => {} }; + } elsif(defined($value)) { + my %names; + for my $name (split /,/, $value) { + $names{$name} = 1; + } + return { active => 1, filter => 1, hash => \%names }; + } else { + return { active => 1, filter => 0, hash => {} }; + } +} + +my %options = ( + "debug" => { default => 0, description => "debug mode" }, + "help" => { default => 0, description => "help mode" }, + "verbose" => { default => 0, description => "verbose mode" }, + + "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" }, + + "local" => { default => 1, description => "local checking" }, + "module" => { + default => { active => 1, filter => 0, hash => {} }, + parent => "local", + parser => \&parser_comma_list, + description => "module filter" + }, + + "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 => {} }, + parent => "argument", + parser => \&parser_comma_list, + description => "argument forbidden checking" + }, + "argument-kind" => { + default => { active => 0, filter => 0, hash => {} }, + parent => "argument", + parser => \&parser_comma_list, + description => "argument kind checking" + }, + "calling-convention" => { default => 0, parent => "local", description => "calling convention checking" }, + "misplaced" => { default => 0, parent => "local", description => "checking for misplaced functions" }, + + "global" => { default => 1, description => "global checking" }, + "declared" => { default => 1, parent => "global", description => "declared checking" }, + "implemented" => { default => 0, parent => "global", description => "implemented checking" } + +); + +my %short_options = ( + "d" => "debug", + "?" => "help", + "v" => "verbose" +); + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = {}; + bless ($self, $class); + + my $refarguments = shift; + my @ARGV = @$refarguments; + + for my $name (sort(keys(%options))) { + my $option = $options{$name}; + my $key = uc($name); + $key =~ tr/-/_/; + $$option{key} = $key; + my $refvalue = \${$self->{$key}}; + $$refvalue = $$option{default}; + } + + my $files = \@{$self->{FILES}}; + my $module = \${$self->{MODULE}}; + my $global = \${$self->{GLOBAL}}; + + while(defined($_ = shift @ARGV)) { + if(/^-([^=]*)(=(.*))?$/) { + my $name; + my $value; + if(defined($2)) { + $name = $1; + $value = $3; + } else { + $name = $1; + } + + if($name =~ /^([^-].*)$/) { + $name = $short_options{$1}; + } else { + $name =~ s/^-(.*)$/$1/; + } + + my $prefix; + if($name =~ /^no-(.*)$/) { + $name = $1; + $prefix = "no"; + if(defined($value)) { + print STDERR ": options with prefix 'no' can't take parameters\n"; + exit 1; + } + } + + my $option = $options{$name}; + if(defined($option)) { + my $key = $$option{key}; + my $parser = $$option{parser}; + my $refvalue = \${$self->{$key}}; + + if(defined($parser)) { + $$refvalue = &$parser($prefix,$value); + } else { + if(defined($value)) { + $$refvalue = $value; + } elsif(!defined($prefix)) { + $$refvalue = 1; + } else { + $$refvalue = 0; + } + } + next; + } + } + + if(/^--module-dlls$/) { + my @dirs = `cd dlls && find ./ -type d ! -name CVS`; + my %names; + for my $dir (@dirs) { + chomp $dir; + $dir =~ s/^\.\/(.*)$/$1/; + next if $dir eq ""; + $names{$dir} = 1; + } + $$module = { active => 1, filter => 1, hash => \%names }; + } + elsif(/^-(.*)$/) { + print STDERR ": unknown option: $&\n"; + print STDERR ": usage: winapi-check [--help] []\n"; + exit 1; + } else { + push @$files, $_; + } + } + + if($#$files == -1) { + @$files = map { + s/^.\/(.*)$/$1/; + $_; + } split(/\n/, `find . -name \\*.c`); + } else { + $$global = 0 + } + + return $self; +} + +sub show_help { + my $self = shift; + + my $maxname = 0; + for my $name (sort(keys(%options))) { + if(length($name) > $maxname) { + $maxname = length($name); + } + } + + print "usage: winapi-check [--help] []\n"; + print "\n"; + for my $name (sort(keys(%options))) { + my $option = $options{$name}; + my $description = $$option{description}; + my $default = $$option{default}; + + my $output; + if(ref($default) ne "HASH") { + if($default) { + $output = "--no-$name"; + } else { + $output = "--$name"; + } + } else { + if($default->{active}) { + $output = "--[no-]$name\[=]"; + } else { + $output = "--$name\[=]"; + } + } + + print "$output"; + for (0..(($maxname - length($name) + 14) - (length($output) - length($name) + 1))) { print " "; } + if(ref($default) ne "HASH") { + if($default) { + print "Disable $description\n"; + } else { + print "Enable $description\n"; + } + } else { + if($default->{active}) { + print "(Disable) $description\n"; + } else { + print "Enable $description\n"; + } + + + } + } +} + +sub AUTOLOAD { + my $self = shift; + + my $name = $winapi_options::AUTOLOAD; + $name =~ s/^.*::(.[^:]*)$/\U$1/; + + my $refvalue = $self->{$name}; + if(!defined($refvalue)) { + die ": winapi_options.pm: member $name does not exists\n"; + } + return $$refvalue; +} + +sub files { my $self = shift; return @{$self->{FILES}}; } + +sub report_module { + my $self = shift; + my $module = $self->module; + + my $name = shift; + + if(defined($name)) { + return $module->{active} && (!$module->{filter} || $module->{hash}->{$name}); + } else { + return 0; + } +} + +sub report_argument_forbidden { + my $self = shift; + my $argument_forbidden = $self->argument_forbidden; + + my $type = shift; + + return $argument_forbidden->{active} && (!$argument_forbidden->{filter} || $argument_forbidden->{hash}->{$type}); +} + +sub report_argument_kind { + my $self = shift; + my $argument_kind = $self->argument_kind; + + my $kind = shift; + + return $argument_kind->{active} && (!$argument_kind->{filter} || $argument_kind->{hash}->{$kind}); + +} + +1; + diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm new file mode 100644 index 00000000000..7e331a5d488 --- /dev/null +++ b/tools/winapi_check/winapi_parser.pm @@ -0,0 +1,161 @@ +package winapi_parser; + +use strict; + +sub parse_c_file { + my $options = shift; + my $file = shift; + my $function_found_callback = shift; + + my $level = 0; + my $again = 0; + my $lookahead = 0; + my $lookahead_count = 0; + + print STDERR "Processing file '$file' ... " if $options->verbose; + open(IN, "< $file") || die ": $file: $!\n"; + $/ = "\n"; + while($again || defined(my $line = )) { + if(!$again) { + chomp $line; + + if($lookahead) { + $lookahead = 0; + $_ .= "\n" . $line; + } else { + $_ = $line; + $lookahead_count = 0; + } + $lookahead_count++; + print "$level: $line\n" if $options->debug >= 2; + } else { + $lookahead_count = 0; + $again = 0; + } + + # remove comments + if(s/^(.*?)\/\*.*?\*\/(.*)$/$1 $2/s) { $again = 1; next }; + if(/^(.*?)\/\*/s) { + $lookahead = 1; + next; + } + + # remove empty rows + if(/^\s*$/) { next; } + + # remove preprocessor directives + if(s/^\s*\#.*$//m) { $again = 1; next; } + + if($level > 0) + { + s/^[^\{\}]*//s; + if(/^\{/) { + $_ = $'; $again = 1; + print "+1: $_\n" if $options->debug >= 2; + $level++; + } elsif(/^\}/) { + $_ = $'; $again = 1; + print "-1: $_\n" if $options->debug >= 2; + $level--; + } + next; + } 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 ";") { + next; + } elsif($9 eq "{") { + $level++; + } + + my $return_type = $1; + my $calling_convention = $5; + my $name = $6; + my $arguments = $8; + + $return_type =~ s/\s*$//; + $return_type =~ s/\s*\*\s*/*/g; + $return_type =~ s/(\*+)/ $1/g; + + $name =~ s/^REGS_FUNC\((.*?)\)/$1/; + + $arguments =~ y/\t\n/ /; + $arguments =~ s/^\s*(.*?)\s*$/$1/; + if($arguments eq "") { $arguments = "void" } + + my @arguments = split(/,/, $arguments); + foreach my $n (0..$#arguments) { + my $argument = $arguments[$n]; + $argument =~ s/^\s*(.*?)\s*$/$1/; + #print " " . ($n + 1) . ": '$argument'\n"; + $argument =~ s/^(const(?=\s)|IN(?=\s)|OUT(?=\s)|(\s*))\s*//; + if($argument =~ /^...$/) { + $argument = "..."; + } elsif($argument =~ /^((struct\s+|union\s+|enum\s+)?\w+)\s*((\*\s*?)*)\s*/) { + $argument = "$1"; + if($3 ne "") { + $argument .= " $3"; + } + } else { + die "$file: $.: syntax error: '$argument'\n"; + } + $arguments[$n] = $argument; + #print " " . ($n + 1) . ": '" . $arguments[$n] . "'\n"; + } + if($#arguments == 0 && $arguments[0] =~ /^void$/i) { $#arguments = -1; } + + if($options->debug) { + print "$file: $return_type $calling_convention $name(" . join(",", @arguments) . ")\n"; + } + &$function_found_callback($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); + } elsif(/DC_(GET_VAL_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,.*?\)/s) { + $_ = $'; $again = 1; + my @arguments = ("HDC"); + &$function_found_callback($2, "WINAPI", $3, \@arguments); + } 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); + } 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); + } elsif(/WAVEOUT_SHORTCUT_(1|2)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) { + $_ = $'; $again = 1; + print "$_"; + 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); + } 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) + } + } elsif(/;/s) { + $_ = $'; $again = 1; + } elsif(/\{/s) { + $_ = $'; $again = 1; + print "+1: $_\n" if $options->debug >= 2; + $level++; + } else { + $lookahead = 1; + } + } + close(IN); + print STDERR "done\n" if $options->verbose; + print "$file: <>: not at toplevel at end of file\n" unless $level == 0; +} + +1;