home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_04 / Skimmer / Skimmer.cpp < prev    next >
C/C++ Source or Header  |  2000-05-11  |  8KB  |  463 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : skimmer.cpp                                                         //
  10. //  Description: Simple parser for Win32 header file                                 //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include <stdio.h>
  19.  
  20.  
  21. class KParser
  22. {
  23.     typedef enum { MAX_TYPES = 512,
  24.                    MAX_NAMELEN = 64
  25.                 };
  26.     HANDLE str;
  27.     HANDLE hmap;
  28.     char * view;
  29.     
  30.     int       size;
  31.     int       pos;
  32.  
  33.     char   typnam[MAX_TYPES][MAX_NAMELEN];
  34.     int       types;
  35.  
  36. public:
  37.  
  38.     bool Open(const char * file)
  39.     {
  40.         str = CreateFile(file, 
  41.                            GENERIC_READ, FILE_SHARE_READ, NULL,
  42.                                OPEN_EXISTING,
  43.                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  44.  
  45.         if ( str == INVALID_HANDLE_VALUE )
  46.             return false;
  47.  
  48.         size = GetFileSize(str, NULL);
  49.  
  50.         hmap = CreateFileMapping(str, NULL, PAGE_READONLY, 0, 0, NULL);
  51.  
  52.         if ( hmap )
  53.             view = (char *) MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
  54.  
  55.         ch = ' ';
  56.         pos = 0;
  57.  
  58.         types = 0;
  59.  
  60.         return true;
  61.     }
  62.  
  63.     char ch;
  64.     char token[MAX_PATH];
  65.  
  66.     void Close(void)
  67.     {
  68.         UnmapViewOfFile(view);
  69.         CloseHandle(hmap);
  70.         CloseHandle(str);
  71.     }
  72.  
  73.     bool Eof(void)
  74.     {
  75.         return pos >= size;
  76.     }
  77.  
  78.     bool Equal(const char *check);
  79.  
  80.     void Nextch(void);
  81.     void NextToken(void);
  82.  
  83.     void CheckType(char *word);
  84.     void CheckTypes(char * line);
  85.     void DumpTypes();
  86.     
  87.     void CheckAPI(void);
  88. };
  89.  
  90.  
  91. void KParser::CheckType(char * word)
  92. {
  93.     while ( * word==' ' )
  94.         word ++;
  95.  
  96.     int len = strlen(word);
  97.  
  98.     while ( len && word[len-1]==' ' )
  99.     {
  100.         len --;
  101.         word[len]=0;
  102.     }
  103.  
  104.     if ( len==0 )
  105.         return;
  106.  
  107.     for (int i=0; i<types; i++)
  108.         if ( strcmp(word, typnam[i])==0 )
  109.             return;
  110.  
  111.     strcpy(typnam[types], word);
  112.     types ++;
  113. }
  114.  
  115.  
  116. void KParser::DumpTypes(void)
  117. {
  118.     printf("\n");
  119.     printf("[Types]\n");
  120.  
  121.     for (int i=0; i<types; i++)
  122.     {
  123.         printf(typnam[i]);
  124.         printf("\n");
  125.     }
  126. }
  127.  
  128.  
  129. // type func(t1,t2,...tn)
  130. //      ^15
  131. void KParser::CheckTypes(char * line)
  132. {
  133.     line[14] = 0;
  134.  
  135.     CheckType(line);
  136.  
  137.     line = strchr(line+15, '(');
  138.  
  139.     if ( line )
  140.     {
  141.         line ++;
  142.         char * p;
  143.  
  144.         while ( p = strchr(line, ',') )
  145.         {
  146.             * p = 0;
  147.             CheckType(line);
  148.  
  149.             line = p+1;
  150.         }
  151.  
  152.         p = strchr(line, ')');
  153.  
  154.         if ( p )
  155.         {
  156.             * p = 0;
  157.             CheckType(line);
  158.         }
  159.     }
  160. }
  161.  
  162.  
  163. void KParser::Nextch(void)
  164. {
  165.     do
  166.     { 
  167.         ch = * view ++; 
  168.         pos ++;
  169.     }
  170.     while (ch=='\r');   // skip '\r'
  171.     
  172.     if ( ch=='\t' ) 
  173.         ch=' ';         // map tab to space
  174. }
  175.  
  176.  
  177. void KParser::NextToken(void)
  178. {
  179. again:
  180.     token[0] = 0;
  181.  
  182.     if ( Eof() )
  183.         return;
  184.  
  185.     while ( ch==' ' )
  186.         Nextch();
  187.  
  188.     if ( ch=='\n' )
  189.     {
  190.         token[0] = ch;
  191.         token[1] = 0;
  192.  
  193.         Nextch();
  194.         return;
  195.     }
  196.     
  197.     if ( ch=='/' )
  198.     {
  199.         Nextch();
  200.     
  201.         if ( ch=='/' )                // single line commented
  202.         {
  203.             while ( ch!='\n') 
  204.                 Nextch();
  205.             Nextch();
  206.             goto again;
  207.         }
  208.  
  209.         if ( ch=='*' )                // block comment /* ... */, nesting not allowed
  210.         {
  211.             Nextch();
  212.             
  213.         more:
  214.             while ( ch!='*')
  215.                 Nextch();
  216.  
  217.             Nextch();
  218.             if ( ch=='/' )
  219.             {
  220.                 Nextch();
  221.                 goto again;
  222.             }
  223.             else
  224.                 goto more;
  225.         }
  226.  
  227.         token[0] = '/';
  228.         token[1] = 0;
  229.  
  230.         return;
  231.     }
  232.  
  233.     int len = 0;
  234.     
  235.     // simple single character delimiters
  236.     switch ( ch )
  237.     {
  238.         case '(':
  239.         case ')':
  240.         case ',':
  241.         case ';':
  242.         case '[':
  243.         case ']':
  244.         case '+':
  245.         case '*': 
  246.             token[len++] = ch;
  247.             token[len] = 0;
  248.             Nextch();
  249.             return;
  250.     }
  251.     
  252.     // identifiers or keywords
  253.     if ( (ch=='_') || isalpha(ch) )
  254.     {
  255.         token[len++] = ch;
  256.         Nextch();
  257.  
  258.         while ( (ch=='_') || isalpha(ch) || isdigit(ch) )
  259.         {
  260.             token[len++] = ch;
  261.             Nextch();
  262.         }
  263.  
  264.         token[len] = 0;
  265.         return;
  266.     }
  267.  
  268.     // others
  269.     while ( (ch!=' ') && (ch!='\n') )
  270.     {
  271.         token[len++] = ch;
  272.         Nextch();
  273.     }
  274.  
  275.     token[len] = 0;
  276. }
  277.  
  278.  
  279. bool KParser::Equal(const char * check)
  280. {
  281.     return strcmp(token, check)==0;
  282. }
  283.  
  284.  
  285. // DECLARE_INTERFACE_( IDirectDraw, IUnknown )
  286. //
  287. //  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
  288. //  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
  289.  
  290. void KParser::CheckAPI(void)
  291. {
  292.     NextToken();
  293.  
  294.     // first token after a new line
  295.     if ( Equal("DECLARE_INTERFACE_") )
  296.     {
  297.         NextToken();        // (
  298.         NextToken();        // interface name
  299.  
  300.         printf("\n[%s]\n", token);
  301.  
  302.         return;
  303.     }
  304.  
  305.     // <newline> WINGDIAPI
  306.     char line[MAX_PATH];
  307.     
  308.     line[0] = 0;
  309.  
  310.     int isapi = 0;
  311.     
  312.     int identadmit = 100;
  313.  
  314.     while ( ! Eof() && (isapi || token[0]!='\n') )
  315.     {
  316.         // rejecting pragmas
  317.         if ( Equal("#define") || Equal("#ifdef") || Equal("#ifndef") ||
  318.              Equal("#else") || Equal("#endif") || Equal("typedef") 
  319.            )
  320.             return;
  321.  
  322.         // API signals
  323.         if ( Equal("WINGDIAPI") || Equal("WINUSERAPI") || 
  324.              Equal("WINAPI") || Equal("APIENTRY") )
  325.         {
  326.             isapi = true;
  327.             NextToken();
  328.             continue;
  329.         }
  330.  
  331.         //  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
  332.         if ( Equal("STDMETHOD") )
  333.         {
  334.             isapi = true;
  335.  
  336.             NextToken(); // (
  337.             strcat(line, "HRESULT");
  338.             while ( strlen(line)<15 )
  339.                 strcat(line, " ");
  340.  
  341.             NextToken();            // name
  342.             strcat(line, token);
  343.             NextToken();        // )
  344.  
  345.             NextToken();        // (
  346.         }
  347.  
  348.         // STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
  349.         if ( Equal("STDMETHOD_") )
  350.         {
  351.             isapi = true;
  352.  
  353.             NextToken(); // (
  354.             NextToken(); // type
  355.             strcat(line, token);
  356.             while ( strlen(line)<15 )
  357.                 strcat(line, " ");
  358.  
  359.             NextToken();            // ,
  360.             NextToken();            // name
  361.             strcat(line, token);
  362.             NextToken();        // )
  363.  
  364.             NextToken();        // (
  365.         }
  366.     
  367.         if ( Equal("THIS_") )
  368.         {
  369.             strcat(line, "THIS");
  370.             strcpy(token, ",");
  371.         }
  372.  
  373.         // skipped words
  374.         if ( Equal("IN")       || Equal("OUT") || 
  375.              Equal("CONST") || Equal("FAR")  || 
  376.              Equal("extern")   || Equal("PURE") ||
  377.              token[0]=='\n'     
  378.            )
  379.         {
  380.             NextToken();
  381.             continue;
  382.         }
  383.  
  384.         // ; is the end
  385.         if ( token[0] == ';' )
  386.         {
  387.             if ( isapi )
  388.             {
  389.                 printf(line);
  390.                 printf("\n");
  391.  
  392.                 CheckTypes(line);
  393.             }
  394.  
  395.             NextToken();
  396.             return;
  397.         }
  398.  
  399.         char copy[MAX_PATH];
  400.         strcpy(copy, token);
  401.  
  402.         NextToken();
  403.  
  404.         // before adding '(', add space to function name
  405.         if ( token[0]=='(' )
  406.             while ( strlen(line)<15 )
  407.                 strcat(line, " ");
  408.  
  409.         // skip parameter name
  410.         if ( copy[0]=='_' || isalpha(copy[0]) )
  411.         {
  412.             if ( identadmit )
  413.             {
  414.                 identadmit --;
  415.                 strcat(line, copy);
  416.             }
  417.         }
  418.         else
  419.             strcat(line, copy);
  420.  
  421.         // after '(' or ',', one identifier only
  422.         if ( copy[0]=='(' || copy[0]==',' )
  423.             identadmit = 1;
  424.     }
  425. }            
  426.  
  427.  
  428. int main( int argc, char *argv[ ], char *envp[ ] )
  429. {
  430.     KParser parser;
  431.  
  432.     if ( argc<2 )
  433.     {
  434.         printf("Skimmer: extracts function prototypes from Windows API header file\n");
  435.         printf("Usage: skimmer <headerfilename>\n");
  436.         return -1;
  437.     }
  438.  
  439.     if ( !parser.Open(argv[1]) )
  440.     {
  441.         printf("Unable to open %s.\n", argv[1]);
  442.         return -1;
  443.     }
  444.  
  445.     parser.token[0] = '\n';
  446.     parser.token[1] = 0;
  447.  
  448.     printf("[%s]\n", argv[1]);
  449.  
  450.     while ( ! parser.Eof() )
  451.     {
  452.         if ( parser.token[0] == '\n' ) // starting with a newline, check API
  453.             parser.CheckAPI();
  454.         else
  455.             parser.NextToken();
  456.     }
  457.     
  458.     parser.DumpTypes();
  459.  
  460.     parser.Close();
  461.  
  462.     return 0;
  463. }