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
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
,
68 /* compute hash value */
69 len
= (int)(end
- name
);
71 for ( nn
= 0; nn
< len
; nn
++ )
74 /* check for an pre-existing name */
75 for ( nn
= 0; nn
< num_names
; nn
++ )
79 if ( (int)nm
->hash
== h
&&
80 memcmp( name
, nm
->name
, len
) == 0 &&
86 if ( num_names
>= max_names
)
88 max_names
+= (max_names
>> 1) + 4;
89 the_names
= (NameRec
*)realloc( the_names
, sizeof(the_names
[0])*max_names
);
90 if ( the_names
== NULL
)
91 panic( "not enough memory" );
93 nm
= &the_names
[num_names
++];
96 nm
->name
= (char*)malloc( len
+1 );
97 if ( nm
->name
== NULL
)
98 panic( "not enough memory" );
100 memcpy( nm
->name
, name
, len
);
106 name_compare( const void* name1
,
109 Name n1
= (Name
)name1
;
110 Name n2
= (Name
)name2
;
112 return strcmp( n1
->name
, n2
->name
);
118 qsort( the_names
, (size_t)num_names
, sizeof(the_names
[0]), name_compare
);
123 names_dump( FILE* out
,
125 const char* dll_name
)
131 case OUTPUT_WINDOWS_DEF
:
133 fprintf( out
, "LIBRARY %s\n", dll_name
);
135 fprintf( out
, "DESCRIPTION FreeType 2 DLL\n" );
136 fprintf( out
, "EXPORTS\n" );
137 for ( nn
= 0; nn
< num_names
; nn
++ )
138 fprintf( out
, " %s\n", the_names
[nn
].name
);
141 case OUTPUT_BORLAND_DEF
:
143 fprintf( out
, "LIBRARY %s\n", dll_name
);
145 fprintf( out
, "DESCRIPTION FreeType 2 DLL\n" );
146 fprintf( out
, "EXPORTS\n" );
147 for ( nn
= 0; nn
< num_names
; nn
++ )
148 fprintf( out
, " _%s\n", the_names
[nn
].name
);
151 case OUTPUT_WATCOM_LBC
:
153 /* we must omit the .dll suffix from the library name */
157 if ( dll_name
== NULL
)
160 "you must provide a DLL name with the -d option !!\n" );
164 dot
= strchr( dll_name
, '.' );
167 int len
= (dot
- dll_name
);
168 if ( len
> (int)(sizeof(temp
)-1) )
169 len
= sizeof(temp
)-1;
171 memcpy( temp
, dll_name
, len
);
174 dll_name
= (const char*)temp
;
177 for ( nn
= 0; nn
< num_names
; nn
++ )
178 fprintf( out
, "++_%s.%s.%s\n", the_names
[nn
].name
, dll_name
,
179 the_names
[nn
].name
);
184 for ( nn
= 0; nn
< num_names
; nn
++ )
185 fprintf( out
, "%s\n", the_names
[nn
].name
);
192 /* states of the line parser */
196 STATE_START
= 0, /* waiting for FT_EXPORT keyword and return type */
197 STATE_TYPE
/* type was read, waiting for function name */
202 read_header_file( FILE* file
, int verbose
)
204 static char buff
[ LINEBUFF_SIZE
+1 ];
205 State state
= STATE_START
;
207 while ( !feof( file
) )
211 if ( !fgets( buff
, LINEBUFF_SIZE
, file
) )
216 while ( *p
&& (*p
== ' ' || *p
== '\\') ) /* skip leading whitespace */
219 if ( *p
== '\n' || *p
== '\r' ) /* skip empty lines */
226 if ( memcmp( p
, "FT_EXPORT(", 10 ) != 0 )
232 if ( *p
== 0 || *p
== '\n' || *p
== '\r' )
246 /* sometimes, the name is just after the FT_EXPORT(...), so
247 * skip whitespace, and fall-through if we find an alphanumeric
250 while ( *p
== ' ' || *p
== '\t' )
262 while ( isalnum(*p
) || *p
== '_' )
268 fprintf( stderr
, ">>> %.*s\n", p
-name
, name
);
270 names_add( name
, p
);
292 static const char* const format
=
293 "%s %s: extract FreeType API names from header files\n\n"
294 "this program is used to extract the list of public FreeType API\n"
295 "functions. It receives the list of header files as argument and\n"
296 "generates a sorted list of unique identifiers\n\n"
298 "usage: %s header1 [options] [header2 ...]\n\n"
300 "options: - : parse the content of stdin, ignore arguments\n"
301 " -v : verbose mode, output sent to standard error\n"
302 " -oFILE : write output to FILE instead of standard output\n"
303 " -dNAME : indicate DLL file name, 'freetype.dll' by default\n"
304 " -w : output .DEF file for Visual C++ and Mingw\n"
305 " -wB : output .DEF file for Borland C++\n"
306 " -wW : output Watcom Linker Response File\n"
319 int main( int argc
, const char* const* argv
)
323 OutputFormat format
= OUTPUT_LIST
; /* the default */
325 const char* library_name
= NULL
;
330 /* '-' used as a single argument means read source file from stdin */
331 while ( argc
> 1 && argv
[1][0] == '-' )
333 const char* arg
= argv
[1];
354 out
= fopen( arg
, "wt" );
357 fprintf( stderr
, "could not open '%s' for writing\n", argv
[2] );
379 format
= OUTPUT_WINDOWS_DEF
;
383 format
= OUTPUT_BORLAND_DEF
;
387 format
= OUTPUT_WATCOM_LBC
;
412 read_header_file( stdin
, verbose
);
416 for ( --argc
, argv
++; argc
> 0; argc
--, argv
++ )
418 FILE* file
= fopen( argv
[0], "rb" );
421 fprintf( stderr
, "unable to open '%s'\n", argv
[0] );
425 fprintf( stderr
, "opening '%s'\n", argv
[0] );
427 read_header_file( file
, verbose
);
433 if ( num_names
== 0 )
434 panic( "could not find exported functions !!\n" );
437 names_dump( out
, format
, library_name
);