ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

apinames.c
Go to the documentation of this file.
00001 /*
00002  * This little program is used to parse the FreeType headers and
00003  * find the declaration of all public APIs.  This is easy, because
00004  * they all look like the following:
00005  *
00006  *   FT_EXPORT( return_type )
00007  *   function_name( function arguments );
00008  *
00009  * You must pass the list of header files as arguments.  Wildcards are
00010  * accepted if you are using GCC for compilation (and probably by
00011  * other compilers too).
00012  *
00013  * Author: David Turner, 2005, 2006, 2008, 2009, 2010
00014  *
00015  * This code is explicitly placed into the public domain.
00016  *
00017  */
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <ctype.h>
00023 
00024 #define  PROGRAM_NAME     "apinames"
00025 #define  PROGRAM_VERSION  "0.1"
00026 
00027 #define  LINEBUFF_SIZE  1024
00028 
00029 typedef enum  OutputFormat_
00030 {
00031   OUTPUT_LIST = 0,      /* output the list of names, one per line             */
00032   OUTPUT_WINDOWS_DEF,   /* output a Windows .DEF file for Visual C++ or Mingw */
00033   OUTPUT_BORLAND_DEF,   /* output a Windows .DEF file for Borland C++         */
00034   OUTPUT_WATCOM_LBC     /* output a Watcom Linker Command File                */
00035 
00036 } OutputFormat;
00037 
00038 
00039 static void
00040 panic( const char*  message )
00041 {
00042   fprintf( stderr, "PANIC: %s\n", message );
00043   exit(2);
00044 }
00045 
00046 
00047 typedef struct  NameRec_
00048 {
00049   char*         name;
00050   unsigned int  hash;
00051 
00052 } NameRec, *Name;
00053 
00054 static Name  the_names;
00055 static int   num_names;
00056 static int   max_names;
00057 
00058 static void
00059 names_add( const char*  name,
00060            const char*  end )
00061 {
00062   int   nn, len, h;
00063   Name  nm;
00064 
00065   if ( end <= name )
00066     return;
00067 
00068   /* compute hash value */
00069   len = (int)(end - name);
00070   h   = 0;
00071   for ( nn = 0; nn < len; nn++ )
00072     h = h*33 + name[nn];
00073 
00074   /* check for an pre-existing name */
00075   for ( nn = 0; nn < num_names; nn++ )
00076   {
00077     nm = the_names + nn;
00078 
00079     if ( (int)nm->hash                 == h &&
00080          memcmp( name, nm->name, len ) == 0 &&
00081          nm->name[len]                 == 0 )
00082       return;
00083   }
00084 
00085   /* add new name */
00086   if ( num_names >= max_names )
00087   {
00088     max_names += (max_names >> 1) + 4;
00089     the_names  = (NameRec*)realloc( the_names, sizeof(the_names[0])*max_names );
00090     if ( the_names == NULL )
00091       panic( "not enough memory" );
00092   }
00093   nm = &the_names[num_names++];
00094 
00095   nm->hash = h;
00096   nm->name = (char*)malloc( len+1 );
00097   if ( nm->name == NULL )
00098     panic( "not enough memory" );
00099 
00100   memcpy( nm->name, name, len );
00101   nm->name[len] = 0;
00102 }
00103 
00104 
00105 static int
00106 name_compare( const void*  name1,
00107               const void*  name2 )
00108 {
00109   Name  n1 = (Name)name1;
00110   Name  n2 = (Name)name2;
00111 
00112   return strcmp( n1->name, n2->name );
00113 }
00114 
00115 static void
00116 names_sort( void )
00117 {
00118   qsort( the_names, (size_t)num_names, sizeof(the_names[0]), name_compare );
00119 }
00120 
00121 
00122 static void
00123 names_dump( FILE*         out,
00124             OutputFormat  format,
00125             const char*   dll_name )
00126 {
00127   int  nn;
00128 
00129 
00130   switch ( format )
00131   {
00132     case OUTPUT_WINDOWS_DEF:
00133       if ( dll_name )
00134         fprintf( out, "LIBRARY %s\n", dll_name );
00135 
00136       fprintf( out, "DESCRIPTION  FreeType 2 DLL\n" );
00137       fprintf( out, "EXPORTS\n" );
00138       for ( nn = 0; nn < num_names; nn++ )
00139         fprintf( out, "  %s\n", the_names[nn].name );
00140       break;
00141 
00142     case OUTPUT_BORLAND_DEF:
00143       if ( dll_name )
00144         fprintf( out, "LIBRARY %s\n", dll_name );
00145 
00146       fprintf( out, "DESCRIPTION  FreeType 2 DLL\n" );
00147       fprintf( out, "EXPORTS\n" );
00148       for ( nn = 0; nn < num_names; nn++ )
00149         fprintf( out, "  _%s\n", the_names[nn].name );
00150       break;
00151 
00152     case OUTPUT_WATCOM_LBC:
00153       {
00154         /* we must omit the .dll suffix from the library name */
00155         char         temp[512];
00156         const char*  dot;
00157 
00158 
00159         if ( dll_name == NULL )
00160         {
00161           fprintf( stderr,
00162                    "you must provide a DLL name with the -d option!\n" );
00163           exit( 4 );
00164         }
00165 
00166         dot = strchr( dll_name, '.' );
00167         if ( dot != NULL )
00168         {
00169           int  len = dot - dll_name;
00170 
00171 
00172           if ( len > (int)( sizeof( temp ) - 1 ) )
00173             len = sizeof ( temp ) - 1;
00174 
00175           memcpy( temp, dll_name, len );
00176           temp[len] = 0;
00177 
00178           dll_name = (const char*)temp;
00179         }
00180 
00181         for ( nn = 0; nn < num_names; nn++ )
00182           fprintf( out, "++_%s.%s.%s\n", the_names[nn].name, dll_name,
00183                         the_names[nn].name );
00184       }
00185       break;
00186 
00187     default:  /* LIST */
00188       for ( nn = 0; nn < num_names; nn++ )
00189         fprintf( out, "%s\n", the_names[nn].name );
00190   }
00191 }
00192 
00193 
00194 
00195 
00196 /* states of the line parser */
00197 
00198 typedef enum  State_
00199 {
00200   STATE_START = 0,  /* waiting for FT_EXPORT keyword and return type */
00201   STATE_TYPE        /* type was read, waiting for function name      */
00202 
00203 } State;
00204 
00205 static int
00206 read_header_file( FILE*  file, int  verbose )
00207 {
00208   static char  buff[ LINEBUFF_SIZE+1 ];
00209   State        state = STATE_START;
00210 
00211   while ( !feof( file ) )
00212   {
00213     char*  p;
00214 
00215     if ( !fgets( buff, LINEBUFF_SIZE, file ) )
00216       break;
00217 
00218     p = buff;
00219 
00220     while ( *p && (*p == ' ' || *p == '\\') )  /* skip leading whitespace */
00221       p++;
00222 
00223     if ( *p == '\n' || *p == '\r' )  /* skip empty lines */
00224       continue;
00225 
00226     switch ( state )
00227     {
00228       case STATE_START:
00229         {
00230           if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
00231             break;
00232 
00233           p += 10;
00234           for (;;)
00235           {
00236             if ( *p == 0 || *p == '\n' || *p == '\r' )
00237               goto NextLine;
00238 
00239             if ( *p == ')' )
00240             {
00241               p++;
00242               break;
00243             }
00244 
00245             p++;
00246           }
00247 
00248           state = STATE_TYPE;
00249 
00250          /* sometimes, the name is just after the FT_EXPORT(...), so
00251           * skip whitespace, and fall-through if we find an alphanumeric
00252           * character
00253           */
00254           while ( *p == ' ' || *p == '\t' )
00255             p++;
00256 
00257           if ( !isalpha(*p) )
00258             break;
00259         }
00260         /* fall-through */
00261 
00262       case STATE_TYPE:
00263         {
00264           char*   name = p;
00265 
00266           while ( isalnum(*p) || *p == '_' )
00267             p++;
00268 
00269           if ( p > name )
00270           {
00271             if ( verbose )
00272               fprintf( stderr, ">>> %.*s\n", (int)(p - name), name );
00273 
00274             names_add( name, p );
00275           }
00276 
00277           state = STATE_START;
00278         }
00279         break;
00280 
00281       default:
00282         ;
00283     }
00284 
00285   NextLine:
00286     ;
00287   }
00288 
00289   return 0;
00290 }
00291 
00292 
00293 static void
00294 usage( void )
00295 {
00296   static const char* const  format =
00297    "%s %s: extract FreeType API names from header files\n\n"
00298    "this program is used to extract the list of public FreeType API\n"
00299    "functions. It receives the list of header files as argument and\n"
00300    "generates a sorted list of unique identifiers\n\n"
00301 
00302    "usage: %s header1 [options] [header2 ...]\n\n"
00303 
00304    "options:   -      : parse the content of stdin, ignore arguments\n"
00305    "           -v     : verbose mode, output sent to standard error\n"
00306    "           -oFILE : write output to FILE instead of standard output\n"
00307    "           -dNAME : indicate DLL file name, 'freetype.dll' by default\n"
00308    "           -w     : output .DEF file for Visual C++ and Mingw\n"
00309    "           -wB    : output .DEF file for Borland C++\n"
00310    "           -wW    : output Watcom Linker Response File\n"
00311    "\n";
00312 
00313   fprintf( stderr,
00314            format,
00315            PROGRAM_NAME,
00316            PROGRAM_VERSION,
00317            PROGRAM_NAME
00318            );
00319   exit(1);
00320 }
00321 
00322 
00323 int  main( int argc, const char* const*  argv )
00324 {
00325   int           from_stdin = 0;
00326   int           verbose = 0;
00327   OutputFormat  format = OUTPUT_LIST;  /* the default */
00328   FILE*         out    = stdout;
00329   const char*   library_name = NULL;
00330 
00331   if ( argc < 2 )
00332     usage();
00333 
00334   /* '-' used as a single argument means read source file from stdin */
00335   while ( argc > 1 && argv[1][0] == '-' )
00336   {
00337     const char*  arg = argv[1];
00338 
00339     switch ( arg[1] )
00340     {
00341       case 'v':
00342         verbose = 1;
00343         break;
00344 
00345       case 'o':
00346         if ( arg[2] == 0 )
00347         {
00348           if ( argc < 2 )
00349             usage();
00350 
00351           arg = argv[2];
00352           argv++;
00353           argc--;
00354         }
00355         else
00356           arg += 2;
00357 
00358         out = fopen( arg, "wt" );
00359         if ( out == NULL )
00360         {
00361           fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
00362           exit(3);
00363         }
00364         break;
00365 
00366       case 'd':
00367         if ( arg[2] == 0 )
00368         {
00369           if ( argc < 2 )
00370             usage();
00371 
00372           arg = argv[2];
00373           argv++;
00374           argc--;
00375         }
00376         else
00377           arg += 2;
00378 
00379         library_name = arg;
00380         break;
00381 
00382       case 'w':
00383         format = OUTPUT_WINDOWS_DEF;
00384         switch ( arg[2] )
00385         {
00386           case 'B':
00387             format = OUTPUT_BORLAND_DEF;
00388             break;
00389 
00390           case 'W':
00391             format = OUTPUT_WATCOM_LBC;
00392             break;
00393 
00394           case 0:
00395             break;
00396 
00397           default:
00398             usage();
00399         }
00400         break;
00401 
00402       case 0:
00403         from_stdin = 1;
00404         break;
00405 
00406       default:
00407         usage();
00408     }
00409 
00410     argc--;
00411     argv++;
00412   }
00413 
00414   if ( from_stdin )
00415   {
00416     read_header_file( stdin, verbose );
00417   }
00418   else
00419   {
00420     for ( --argc, argv++; argc > 0; argc--, argv++ )
00421     {
00422       FILE*  file = fopen( argv[0], "rb" );
00423 
00424       if ( file == NULL )
00425         fprintf( stderr, "unable to open '%s'\n", argv[0] );
00426       else
00427       {
00428         if ( verbose )
00429           fprintf( stderr, "opening '%s'\n", argv[0] );
00430 
00431         read_header_file( file, verbose );
00432         fclose( file );
00433       }
00434     }
00435   }
00436 
00437   if ( num_names == 0 )
00438     panic( "could not find exported functions !!\n" );
00439 
00440   names_sort();
00441   names_dump( out, format, library_name );
00442 
00443   if ( out != stdout )
00444     fclose( out );
00445 
00446   return 0;
00447 }

Generated on Fri May 25 2012 04:32:32 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.