Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / modules / freetype2 / src / tools / apinames.c
blob19aec500bf253af0e4b09d2583ec994e5f167ed8
1 /*
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.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
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 */
36 } OutputFormat;
39 static void
40 panic( const char* message )
42 fprintf( stderr, "PANIC: %s\n", message );
43 exit(2);
47 typedef struct NameRec_
49 char* name;
50 unsigned int hash;
52 } NameRec, *Name;
54 static Name the_names;
55 static int num_names;
56 static int max_names;
58 static void
59 names_add( const char* name,
60 const char* end )
62 int nn, len, h;
63 Name nm;
65 if ( end <= name )
66 return;
68 /* compute hash value */
69 len = (int)(end - name);
70 h = 0;
71 for ( nn = 0; nn < len; nn++ )
72 h = h*33 + name[nn];
74 /* check for an pre-existing name */
75 for ( nn = 0; nn < num_names; nn++ )
77 nm = the_names + nn;
79 if ( (int)nm->hash == h &&
80 memcmp( name, nm->name, len ) == 0 &&
81 nm->name[len] == 0 )
82 return;
85 /* add new name */
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++];
95 nm->hash = h;
96 nm->name = (char*)malloc( len+1 );
97 if ( nm->name == NULL )
98 panic( "not enough memory" );
100 memcpy( nm->name, name, len );
101 nm->name[len] = 0;
105 static int
106 name_compare( const void* name1,
107 const void* name2 )
109 Name n1 = (Name)name1;
110 Name n2 = (Name)name2;
112 return strcmp( n1->name, n2->name );
115 static void
116 names_sort( void )
118 qsort( the_names, (size_t)num_names, sizeof(the_names[0]), name_compare );
122 static void
123 names_dump( FILE* out,
124 OutputFormat format,
125 const char* dll_name )
127 int nn;
129 switch ( format )
131 case OUTPUT_WINDOWS_DEF:
132 if ( dll_name )
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 );
139 break;
141 case OUTPUT_BORLAND_DEF:
142 if ( dll_name )
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 );
149 break;
151 case OUTPUT_WATCOM_LBC:
153 /* we must omit the .dll suffix from the library name */
154 char temp[512];
155 char* dot;
157 if ( dll_name == NULL )
159 fprintf( stderr,
160 "you must provide a DLL name with the -d option !!\n" );
161 exit(4);
164 dot = strchr( dll_name, '.' );
165 if ( dot != NULL )
167 int len = (dot - dll_name);
168 if ( len > (int)(sizeof(temp)-1) )
169 len = sizeof(temp)-1;
171 memcpy( temp, dll_name, len );
172 temp[len] = 0;
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 );
181 break;
183 default: /* LIST */
184 for ( nn = 0; nn < num_names; nn++ )
185 fprintf( out, "%s\n", the_names[nn].name );
192 /* states of the line parser */
194 typedef enum State_
196 STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
197 STATE_TYPE /* type was read, waiting for function name */
199 } State;
201 static int
202 read_header_file( FILE* file, int verbose )
204 static char buff[ LINEBUFF_SIZE+1 ];
205 State state = STATE_START;
207 while ( !feof( file ) )
209 char* p;
211 if ( !fgets( buff, LINEBUFF_SIZE, file ) )
212 break;
214 p = buff;
216 while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
217 p++;
219 if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
220 continue;
222 switch ( state )
224 case STATE_START:
226 if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
227 break;
229 p += 10;
230 for (;;)
232 if ( *p == 0 || *p == '\n' || *p == '\r' )
233 goto NextLine;
235 if ( *p == ')' )
237 p++;
238 break;
241 p++;
244 state = STATE_TYPE;
246 /* sometimes, the name is just after the FT_EXPORT(...), so
247 * skip whitespace, and fall-through if we find an alphanumeric
248 * character
250 while ( *p == ' ' || *p == '\t' )
251 p++;
253 if ( !isalpha(*p) )
254 break;
256 /* fall-through */
258 case STATE_TYPE:
260 char* name = p;
262 while ( isalnum(*p) || *p == '_' )
263 p++;
265 if ( p > name )
267 if ( verbose )
268 fprintf( stderr, ">>> %.*s\n", p-name, name );
270 names_add( name, p );
273 state = STATE_START;
275 break;
277 default:
281 NextLine:
285 return 0;
289 static void
290 usage( void )
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"
307 "\n";
309 fprintf( stderr,
310 format,
311 PROGRAM_NAME,
312 PROGRAM_VERSION,
313 PROGRAM_NAME
315 exit(1);
319 int main( int argc, const char* const* argv )
321 int from_stdin = 0;
322 int verbose = 0;
323 OutputFormat format = OUTPUT_LIST; /* the default */
324 FILE* out = stdout;
325 const char* library_name = NULL;
327 if ( argc < 2 )
328 usage();
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];
335 switch ( arg[1] )
337 case 'v':
338 verbose = 1;
339 break;
341 case 'o':
342 if ( arg[2] == 0 )
344 if ( argc < 2 )
345 usage();
347 arg = argv[2];
348 argv++;
349 argc--;
351 else
352 arg += 2;
354 out = fopen( arg, "wt" );
355 if ( out == NULL )
357 fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
358 exit(3);
360 break;
362 case 'd':
363 if ( arg[2] == 0 )
365 if ( argc < 2 )
366 usage();
368 arg = argv[2];
369 argv++;
370 argc--;
372 else
373 arg += 2;
375 library_name = arg;
376 break;
378 case 'w':
379 format = OUTPUT_WINDOWS_DEF;
380 switch ( arg[2] )
382 case 'B':
383 format = OUTPUT_BORLAND_DEF;
384 break;
386 case 'W':
387 format = OUTPUT_WATCOM_LBC;
388 break;
390 case 0:
391 break;
393 default:
394 usage();
396 break;
398 case 0:
399 from_stdin = 1;
400 break;
402 default:
403 usage();
406 argc--;
407 argv++;
410 if ( from_stdin )
412 read_header_file( stdin, verbose );
414 else
416 for ( --argc, argv++; argc > 0; argc--, argv++ )
418 FILE* file = fopen( argv[0], "rb" );
420 if ( file == NULL )
421 fprintf( stderr, "unable to open '%s'\n", argv[0] );
422 else
424 if ( verbose )
425 fprintf( stderr, "opening '%s'\n", argv[0] );
427 read_header_file( file, verbose );
428 fclose( file );
433 if ( num_names == 0 )
434 panic( "could not find exported functions !!\n" );
436 names_sort();
437 names_dump( out, format, library_name );
439 if ( out != stdout )
440 fclose( out );
442 return 0;