home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Graphics Programming
/
Feng_Yuan_Win32_GDI_DirectX.iso
/
Samples
/
Chapt_04
/
Skimmer
/
Skimmer.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-11
|
8KB
|
463 lines
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : skimmer.cpp //
// Description: Simple parser for Win32 header file //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
class KParser
{
typedef enum { MAX_TYPES = 512,
MAX_NAMELEN = 64
};
HANDLE str;
HANDLE hmap;
char * view;
int size;
int pos;
char typnam[MAX_TYPES][MAX_NAMELEN];
int types;
public:
bool Open(const char * file)
{
str = CreateFile(file,
GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if ( str == INVALID_HANDLE_VALUE )
return false;
size = GetFileSize(str, NULL);
hmap = CreateFileMapping(str, NULL, PAGE_READONLY, 0, 0, NULL);
if ( hmap )
view = (char *) MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
ch = ' ';
pos = 0;
types = 0;
return true;
}
char ch;
char token[MAX_PATH];
void Close(void)
{
UnmapViewOfFile(view);
CloseHandle(hmap);
CloseHandle(str);
}
bool Eof(void)
{
return pos >= size;
}
bool Equal(const char *check);
void Nextch(void);
void NextToken(void);
void CheckType(char *word);
void CheckTypes(char * line);
void DumpTypes();
void CheckAPI(void);
};
void KParser::CheckType(char * word)
{
while ( * word==' ' )
word ++;
int len = strlen(word);
while ( len && word[len-1]==' ' )
{
len --;
word[len]=0;
}
if ( len==0 )
return;
for (int i=0; i<types; i++)
if ( strcmp(word, typnam[i])==0 )
return;
strcpy(typnam[types], word);
types ++;
}
void KParser::DumpTypes(void)
{
printf("\n");
printf("[Types]\n");
for (int i=0; i<types; i++)
{
printf(typnam[i]);
printf("\n");
}
}
// type func(t1,t2,...tn)
// ^15
void KParser::CheckTypes(char * line)
{
line[14] = 0;
CheckType(line);
line = strchr(line+15, '(');
if ( line )
{
line ++;
char * p;
while ( p = strchr(line, ',') )
{
* p = 0;
CheckType(line);
line = p+1;
}
p = strchr(line, ')');
if ( p )
{
* p = 0;
CheckType(line);
}
}
}
void KParser::Nextch(void)
{
do
{
ch = * view ++;
pos ++;
}
while (ch=='\r'); // skip '\r'
if ( ch=='\t' )
ch=' '; // map tab to space
}
void KParser::NextToken(void)
{
again:
token[0] = 0;
if ( Eof() )
return;
while ( ch==' ' )
Nextch();
if ( ch=='\n' )
{
token[0] = ch;
token[1] = 0;
Nextch();
return;
}
if ( ch=='/' )
{
Nextch();
if ( ch=='/' ) // single line commented
{
while ( ch!='\n')
Nextch();
Nextch();
goto again;
}
if ( ch=='*' ) // block comment /* ... */, nesting not allowed
{
Nextch();
more:
while ( ch!='*')
Nextch();
Nextch();
if ( ch=='/' )
{
Nextch();
goto again;
}
else
goto more;
}
token[0] = '/';
token[1] = 0;
return;
}
int len = 0;
// simple single character delimiters
switch ( ch )
{
case '(':
case ')':
case ',':
case ';':
case '[':
case ']':
case '+':
case '*':
token[len++] = ch;
token[len] = 0;
Nextch();
return;
}
// identifiers or keywords
if ( (ch=='_') || isalpha(ch) )
{
token[len++] = ch;
Nextch();
while ( (ch=='_') || isalpha(ch) || isdigit(ch) )
{
token[len++] = ch;
Nextch();
}
token[len] = 0;
return;
}
// others
while ( (ch!=' ') && (ch!='\n') )
{
token[len++] = ch;
Nextch();
}
token[len] = 0;
}
bool KParser::Equal(const char * check)
{
return strcmp(token, check)==0;
}
// DECLARE_INTERFACE_( IDirectDraw, IUnknown )
//
// STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
// STDMETHOD_(ULONG,AddRef) (THIS) PURE;
void KParser::CheckAPI(void)
{
NextToken();
// first token after a new line
if ( Equal("DECLARE_INTERFACE_") )
{
NextToken(); // (
NextToken(); // interface name
printf("\n[%s]\n", token);
return;
}
// <newline> WINGDIAPI
char line[MAX_PATH];
line[0] = 0;
int isapi = 0;
int identadmit = 100;
while ( ! Eof() && (isapi || token[0]!='\n') )
{
// rejecting pragmas
if ( Equal("#define") || Equal("#ifdef") || Equal("#ifndef") ||
Equal("#else") || Equal("#endif") || Equal("typedef")
)
return;
// API signals
if ( Equal("WINGDIAPI") || Equal("WINUSERAPI") ||
Equal("WINAPI") || Equal("APIENTRY") )
{
isapi = true;
NextToken();
continue;
}
// STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
if ( Equal("STDMETHOD") )
{
isapi = true;
NextToken(); // (
strcat(line, "HRESULT");
while ( strlen(line)<15 )
strcat(line, " ");
NextToken(); // name
strcat(line, token);
NextToken(); // )
NextToken(); // (
}
// STDMETHOD_(ULONG,AddRef) (THIS) PURE;
if ( Equal("STDMETHOD_") )
{
isapi = true;
NextToken(); // (
NextToken(); // type
strcat(line, token);
while ( strlen(line)<15 )
strcat(line, " ");
NextToken(); // ,
NextToken(); // name
strcat(line, token);
NextToken(); // )
NextToken(); // (
}
if ( Equal("THIS_") )
{
strcat(line, "THIS");
strcpy(token, ",");
}
// skipped words
if ( Equal("IN") || Equal("OUT") ||
Equal("CONST") || Equal("FAR") ||
Equal("extern") || Equal("PURE") ||
token[0]=='\n'
)
{
NextToken();
continue;
}
// ; is the end
if ( token[0] == ';' )
{
if ( isapi )
{
printf(line);
printf("\n");
CheckTypes(line);
}
NextToken();
return;
}
char copy[MAX_PATH];
strcpy(copy, token);
NextToken();
// before adding '(', add space to function name
if ( token[0]=='(' )
while ( strlen(line)<15 )
strcat(line, " ");
// skip parameter name
if ( copy[0]=='_' || isalpha(copy[0]) )
{
if ( identadmit )
{
identadmit --;
strcat(line, copy);
}
}
else
strcat(line, copy);
// after '(' or ',', one identifier only
if ( copy[0]=='(' || copy[0]==',' )
identadmit = 1;
}
}
int main( int argc, char *argv[ ], char *envp[ ] )
{
KParser parser;
if ( argc<2 )
{
printf("Skimmer: extracts function prototypes from Windows API header file\n");
printf("Usage: skimmer <headerfilename>\n");
return -1;
}
if ( !parser.Open(argv[1]) )
{
printf("Unable to open %s.\n", argv[1]);
return -1;
}
parser.token[0] = '\n';
parser.token[1] = 0;
printf("[%s]\n", argv[1]);
while ( ! parser.Eof() )
{
if ( parser.token[0] == '\n' ) // starting with a newline, check API
parser.CheckAPI();
else
parser.NextToken();
}
parser.DumpTypes();
parser.Close();
return 0;
}