2 * This little program is used to parse the FreeType headers and
3 * find the declaration of all public APIs. This is easy, because
4 * they all look like the following:
6 * FT_EXPORT( return_type )
7 * function_name( function arguments );
9 * You must pass the list of header files as arguments. Wildcards are
10 * accepted if you are using GCC for compilation (and probably by
11 * other compilers too).
13 * Author: David Turner, 2005, 2006, 2008-2012
15 * This code is explicitly placed into the public domain.
24 #define PROGRAM_NAME "apinames"
25 #define PROGRAM_VERSION "0.1"
27 #define LINEBUFF_SIZE 1024
29 typedef enum OutputFormat_
31 OUTPUT_LIST = 0, /* output the list of names, one per line */
32 OUTPUT_WINDOWS_DEF, /* output a Windows .DEF file for Visual C++ or Mingw */
33 OUTPUT_BORLAND_DEF, /* output a Windows .DEF file for Borland C++ */
34 OUTPUT_WATCOM_LBC /* output a Watcom Linker Command File */
40 panic( const char* message )
42 fprintf( stderr, "PANIC: %s\n", message );
47 typedef struct NameRec_
54 static Name the_names;
59 names_add( const char* name,
69 /* compute hash value */
70 len = (int)(end - name);
72 for ( nn = 0; nn < len; nn++ )
75 /* check for an pre-existing name */
76 for ( nn = 0; nn < num_names; nn++ )
80 if ( (int)nm->hash == h &&
81 memcmp( name, nm->name, len ) == 0 &&
87 if ( num_names >= max_names )
89 max_names += (max_names >> 1) + 4;
90 the_names = (NameRec*)realloc( the_names,
91 sizeof ( the_names[0] ) * max_names );
92 if ( the_names == NULL )
93 panic( "not enough memory" );
95 nm = &the_names[num_names++];
98 nm->name = (char*)malloc( len+1 );
99 if ( nm->name == NULL )
100 panic( "not enough memory" );
102 memcpy( nm->name, name, len );
108 name_compare( const void* name1,
111 Name n1 = (Name)name1;
112 Name n2 = (Name)name2;
114 return strcmp( n1->name, n2->name );
120 qsort( the_names, (size_t)num_names,
121 sizeof ( the_names[0] ), name_compare );
126 names_dump( FILE* out,
128 const char* dll_name )
135 case OUTPUT_WINDOWS_DEF:
137 fprintf( out, "LIBRARY %s\n", dll_name );
139 fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
140 fprintf( out, "EXPORTS\n" );
141 for ( nn = 0; nn < num_names; nn++ )
142 fprintf( out, " %s\n", the_names[nn].name );
145 case OUTPUT_BORLAND_DEF:
147 fprintf( out, "LIBRARY %s\n", dll_name );
149 fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
150 fprintf( out, "EXPORTS\n" );
151 for ( nn = 0; nn < num_names; nn++ )
152 fprintf( out, " _%s\n", the_names[nn].name );
155 case OUTPUT_WATCOM_LBC:
157 /* we must omit the .dll suffix from the library name */
162 if ( dll_name == NULL )
165 "you must provide a DLL name with the -d option!\n" );
169 dot = strchr( dll_name, '.' );
172 int len = dot - dll_name;
175 if ( len > (int)( sizeof ( temp ) - 1 ) )
176 len = sizeof ( temp ) - 1;
178 memcpy( temp, dll_name, len );
181 dll_name = (const char*)temp;
184 for ( nn = 0; nn < num_names; nn++ )
185 fprintf( out, "++_%s.%s.%s\n", the_names[nn].name, dll_name,
186 the_names[nn].name );
191 for ( nn = 0; nn < num_names; nn++ )
192 fprintf( out, "%s\n", the_names[nn].name );
199 /* states of the line parser */
203 STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
204 STATE_TYPE /* type was read, waiting for function name */
209 read_header_file( FILE* file, int verbose )
211 static char buff[LINEBUFF_SIZE + 1];
212 State state = STATE_START;
214 while ( !feof( file ) )
218 if ( !fgets( buff, LINEBUFF_SIZE, file ) )
223 while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
226 if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
233 if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
239 if ( *p == 0 || *p == '\n' || *p == '\r' )
253 /* sometimes, the name is just after the FT_EXPORT(...), so
254 * skip whitespace, and fall-through if we find an alphanumeric
257 while ( *p == ' ' || *p == '\t' )
269 while ( isalnum(*p) || *p == '_' )
275 fprintf( stderr, ">>> %.*s\n", (int)(p - name), name );
277 names_add( name, p );
299 static const char* const format =
300 "%s %s: extract FreeType API names from header files\n\n"
301 "this program is used to extract the list of public FreeType API\n"
302 "functions. It receives the list of header files as argument and\n"
303 "generates a sorted list of unique identifiers\n\n"
305 "usage: %s header1 [options] [header2 ...]\n\n"
307 "options: - : parse the content of stdin, ignore arguments\n"
308 " -v : verbose mode, output sent to standard error\n"
309 " -oFILE : write output to FILE instead of standard output\n"
310 " -dNAME : indicate DLL file name, 'freetype.dll' by default\n"
311 " -w : output .DEF file for Visual C++ and Mingw\n"
312 " -wB : output .DEF file for Borland C++\n"
313 " -wW : output Watcom Linker Response File\n"
326 int main( int argc, const char* const* argv )
330 OutputFormat format = OUTPUT_LIST; /* the default */
332 const char* library_name = NULL;
337 /* '-' used as a single argument means read source file from stdin */
338 while ( argc > 1 && argv[1][0] == '-' )
340 const char* arg = argv[1];
361 out = fopen( arg, "wt" );
364 fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
386 format = OUTPUT_WINDOWS_DEF;
390 format = OUTPUT_BORLAND_DEF;
394 format = OUTPUT_WATCOM_LBC;
419 read_header_file( stdin, verbose );
423 for ( --argc, argv++; argc > 0; argc--, argv++ )
425 FILE* file = fopen( argv[0], "rb" );
428 fprintf( stderr, "unable to open '%s'\n", argv[0] );
432 fprintf( stderr, "opening '%s'\n", argv[0] );
434 read_header_file( file, verbose );
440 if ( num_names == 0 )
441 panic( "could not find exported functions !!\n" );
444 names_dump( out, format, library_name );