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-2013
15 * This code is explicitly placed into the public domain.
24 #define PROGRAM_NAME "apinames"
25 #define PROGRAM_VERSION "0.2"
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 */
35 OUTPUT_NETWARE_IMP /* output a NetWare ImportFile */
41 panic( const char* message )
43 fprintf( stderr, "PANIC: %s\n", message );
48 typedef struct NameRec_
55 static Name the_names;
60 names_add( const char* name,
70 /* compute hash value */
71 len = (int)(end - name);
73 for ( nn = 0; nn < len; nn++ )
76 /* check for an pre-existing name */
77 for ( nn = 0; nn < num_names; nn++ )
81 if ( (int)nm->hash == h &&
82 memcmp( name, nm->name, len ) == 0 &&
88 if ( num_names >= max_names )
90 max_names += (max_names >> 1) + 4;
91 the_names = (NameRec*)realloc( the_names,
92 sizeof ( the_names[0] ) * max_names );
93 if ( the_names == NULL )
94 panic( "not enough memory" );
96 nm = &the_names[num_names++];
99 nm->name = (char*)malloc( len+1 );
100 if ( nm->name == NULL )
101 panic( "not enough memory" );
103 memcpy( nm->name, name, len );
109 name_compare( const void* name1,
112 Name n1 = (Name)name1;
113 Name n2 = (Name)name2;
115 return strcmp( n1->name, n2->name );
121 qsort( the_names, (size_t)num_names,
122 sizeof ( the_names[0] ), name_compare );
127 names_dump( FILE* out,
129 const char* dll_name )
136 case OUTPUT_WINDOWS_DEF:
138 fprintf( out, "LIBRARY %s\n", dll_name );
140 fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
141 fprintf( out, "EXPORTS\n" );
142 for ( nn = 0; nn < num_names; nn++ )
143 fprintf( out, " %s\n", the_names[nn].name );
146 case OUTPUT_BORLAND_DEF:
148 fprintf( out, "LIBRARY %s\n", dll_name );
150 fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
151 fprintf( out, "EXPORTS\n" );
152 for ( nn = 0; nn < num_names; nn++ )
153 fprintf( out, " _%s\n", the_names[nn].name );
156 case OUTPUT_WATCOM_LBC:
161 if ( dll_name == NULL )
164 "you must provide a DLL name with the -d option!\n" );
168 /* we must omit the .dll suffix from the library name */
169 dot = strchr( dll_name, '.' );
173 int len = dot - dll_name;
176 if ( len > (int)( sizeof ( temp ) - 1 ) )
177 len = sizeof ( temp ) - 1;
179 memcpy( temp, dll_name, len );
182 dll_name = (const char*)temp;
185 for ( nn = 0; nn < num_names; nn++ )
186 fprintf( out, "++_%s.%s.%s\n", the_names[nn].name, dll_name,
187 the_names[nn].name );
191 case OUTPUT_NETWARE_IMP:
193 if ( dll_name != NULL )
194 fprintf( out, " (%s)\n", dll_name );
195 for ( nn = 0; nn < num_names - 1; nn++ )
196 fprintf( out, " %s,\n", the_names[nn].name );
197 fprintf( out, " %s\n", the_names[num_names - 1].name );
202 for ( nn = 0; nn < num_names; nn++ )
203 fprintf( out, "%s\n", the_names[nn].name );
210 /* states of the line parser */
214 STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
215 STATE_TYPE /* type was read, waiting for function name */
220 read_header_file( FILE* file, int verbose )
222 static char buff[LINEBUFF_SIZE + 1];
223 State state = STATE_START;
225 while ( !feof( file ) )
229 if ( !fgets( buff, LINEBUFF_SIZE, file ) )
234 while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
237 if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
244 if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
250 if ( *p == 0 || *p == '\n' || *p == '\r' )
264 /* sometimes, the name is just after the FT_EXPORT(...), so
265 * skip whitespace, and fall-through if we find an alphanumeric
268 while ( *p == ' ' || *p == '\t' )
280 while ( isalnum(*p) || *p == '_' )
286 fprintf( stderr, ">>> %.*s\n", (int)(p - name), name );
288 names_add( name, p );
310 static const char* const format =
311 "%s %s: extract FreeType API names from header files\n\n"
312 "this program is used to extract the list of public FreeType API\n"
313 "functions. It receives the list of header files as argument and\n"
314 "generates a sorted list of unique identifiers\n\n"
316 "usage: %s header1 [options] [header2 ...]\n\n"
318 "options: - : parse the content of stdin, ignore arguments\n"
319 " -v : verbose mode, output sent to standard error\n"
320 " -oFILE : write output to FILE instead of standard output\n"
321 " -dNAME : indicate DLL file name, 'freetype.dll' by default\n"
322 " -w : output .DEF file for Visual C++ and Mingw\n"
323 " -wB : output .DEF file for Borland C++\n"
324 " -wW : output Watcom Linker Response File\n"
325 " -wN : output NetWare Import File\n"
338 int main( int argc, const char* const* argv )
342 OutputFormat format = OUTPUT_LIST; /* the default */
344 const char* library_name = NULL;
349 /* '-' used as a single argument means read source file from stdin */
350 while ( argc > 1 && argv[1][0] == '-' )
352 const char* arg = argv[1];
373 out = fopen( arg, "wt" );
376 fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
398 format = OUTPUT_WINDOWS_DEF;
402 format = OUTPUT_BORLAND_DEF;
406 format = OUTPUT_WATCOM_LBC;
410 format = OUTPUT_NETWARE_IMP;
435 read_header_file( stdin, verbose );
439 for ( --argc, argv++; argc > 0; argc--, argv++ )
441 FILE* file = fopen( argv[0], "rb" );
444 fprintf( stderr, "unable to open '%s'\n", argv[0] );
448 fprintf( stderr, "opening '%s'\n", argv[0] );
450 read_header_file( file, verbose );
456 if ( num_names == 0 )
457 panic( "could not find exported functions !!\n" );
460 names_dump( out, format, library_name );