zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
apinames.c
Go to the documentation of this file.
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:
5  *
6  * FT_EXPORT( return_type )
7  * function_name( function arguments );
8  *
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).
12  *
13  * Author: David Turner, 2005, 2006, 2008-2012
14  *
15  * This code is explicitly placed into the public domain.
16  *
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23 
24 #define PROGRAM_NAME "apinames"
25 #define PROGRAM_VERSION "0.1"
26 
27 #define LINEBUFF_SIZE 1024
28 
29 typedef enum OutputFormat_
30 {
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 
36 } OutputFormat;
37 
38 
39 static void
40 panic( const char* message )
41 {
42  fprintf( stderr, "PANIC: %s\n", message );
43  exit(2);
44 }
45 
46 
47 typedef struct NameRec_
48 {
49  char* name;
50  unsigned int hash;
51 
52 } NameRec, *Name;
53 
54 static Name the_names;
55 static int num_names;
56 static int max_names;
57 
58 static void
59 names_add( const char* name,
60  const char* end )
61 {
62  unsigned int h;
63  int nn, len;
64  Name nm;
65 
66  if ( end <= name )
67  return;
68 
69  /* compute hash value */
70  len = (int)(end - name);
71  h = 0;
72  for ( nn = 0; nn < len; nn++ )
73  h = h*33 + name[nn];
74 
75  /* check for an pre-existing name */
76  for ( nn = 0; nn < num_names; nn++ )
77  {
78  nm = the_names + nn;
79 
80  if ( (int)nm->hash == h &&
81  memcmp( name, nm->name, len ) == 0 &&
82  nm->name[len] == 0 )
83  return;
84  }
85 
86  /* add new name */
87  if ( num_names >= max_names )
88  {
89  max_names += (max_names >> 1) + 4;
91  sizeof ( the_names[0] ) * max_names );
92  if ( the_names == NULL )
93  panic( "not enough memory" );
94  }
95  nm = &the_names[num_names++];
96 
97  nm->hash = h;
98  nm->name = (char*)malloc( len+1 );
99  if ( nm->name == NULL )
100  panic( "not enough memory" );
101 
102  memcpy( nm->name, name, len );
103  nm->name[len] = 0;
104 }
105 
106 
107 static int
108 name_compare( const void* name1,
109  const void* name2 )
110 {
111  Name n1 = (Name)name1;
112  Name n2 = (Name)name2;
113 
114  return strcmp( n1->name, n2->name );
115 }
116 
117 static void
118 names_sort( void )
119 {
120  qsort( the_names, (size_t)num_names,
121  sizeof ( the_names[0] ), name_compare );
122 }
123 
124 
125 static void
126 names_dump( FILE* out,
128  const char* dll_name )
129 {
130  int nn;
131 
132 
133  switch ( format )
134  {
135  case OUTPUT_WINDOWS_DEF:
136  if ( dll_name )
137  fprintf( out, "LIBRARY %s\n", dll_name );
138 
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 );
143  break;
144 
145  case OUTPUT_BORLAND_DEF:
146  if ( dll_name )
147  fprintf( out, "LIBRARY %s\n", dll_name );
148 
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 );
153  break;
154 
155  case OUTPUT_WATCOM_LBC:
156  {
157  /* we must omit the .dll suffix from the library name */
158  char temp[512];
159  const char* dot;
160 
161 
162  if ( dll_name == NULL )
163  {
164  fprintf( stderr,
165  "you must provide a DLL name with the -d option!\n" );
166  exit( 4 );
167  }
168 
169  dot = strchr( dll_name, '.' );
170  if ( dot != NULL )
171  {
172  int len = dot - dll_name;
173 
174 
175  if ( len > (int)( sizeof ( temp ) - 1 ) )
176  len = sizeof ( temp ) - 1;
177 
178  memcpy( temp, dll_name, len );
179  temp[len] = 0;
180 
181  dll_name = (const char*)temp;
182  }
183 
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 );
187  }
188  break;
189 
190  default: /* LIST */
191  for ( nn = 0; nn < num_names; nn++ )
192  fprintf( out, "%s\n", the_names[nn].name );
193  }
194 }
195 
196 
197 
198 
199 /* states of the line parser */
200 
201 typedef enum State_
202 {
203  STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
204  STATE_TYPE /* type was read, waiting for function name */
205 
206 } State;
207 
208 static int
210 {
211  static char buff[LINEBUFF_SIZE + 1];
212  State state = STATE_START;
213 
214  while ( !feof( file ) )
215  {
216  char* p;
217 
218  if ( !fgets( buff, LINEBUFF_SIZE, file ) )
219  break;
220 
221  p = buff;
222 
223  while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
224  p++;
225 
226  if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
227  continue;
228 
229  switch ( state )
230  {
231  case STATE_START:
232  {
233  if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
234  break;
235 
236  p += 10;
237  for (;;)
238  {
239  if ( *p == 0 || *p == '\n' || *p == '\r' )
240  goto NextLine;
241 
242  if ( *p == ')' )
243  {
244  p++;
245  break;
246  }
247 
248  p++;
249  }
250 
251  state = STATE_TYPE;
252 
253  /* sometimes, the name is just after the FT_EXPORT(...), so
254  * skip whitespace, and fall-through if we find an alphanumeric
255  * character
256  */
257  while ( *p == ' ' || *p == '\t' )
258  p++;
259 
260  if ( !isalpha(*p) )
261  break;
262  }
263  /* fall-through */
264 
265  case STATE_TYPE:
266  {
267  char* name = p;
268 
269  while ( isalnum(*p) || *p == '_' )
270  p++;
271 
272  if ( p > name )
273  {
274  if ( verbose )
275  fprintf( stderr, ">>> %.*s\n", (int)(p - name), name );
276 
277  names_add( name, p );
278  }
279 
280  state = STATE_START;
281  }
282  break;
283 
284  default:
285  ;
286  }
287 
288  NextLine:
289  ;
290  }
291 
292  return 0;
293 }
294 
295 
296 static void
297 usage( void )
298 {
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"
304 
305  "usage: %s header1 [options] [header2 ...]\n\n"
306 
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"
314  "\n";
315 
316  fprintf( stderr,
317  format,
318  PROGRAM_NAME,
321  );
322  exit(1);
323 }
324 
325 
326 int main( int argc, const char* const* argv )
327 {
328  int from_stdin = 0;
329  int verbose = 0;
330  OutputFormat format = OUTPUT_LIST; /* the default */
331  FILE* out = stdout;
332  const char* library_name = NULL;
333 
334  if ( argc < 2 )
335  usage();
336 
337  /* '-' used as a single argument means read source file from stdin */
338  while ( argc > 1 && argv[1][0] == '-' )
339  {
340  const char* arg = argv[1];
341 
342  switch ( arg[1] )
343  {
344  case 'v':
345  verbose = 1;
346  break;
347 
348  case 'o':
349  if ( arg[2] == 0 )
350  {
351  if ( argc < 2 )
352  usage();
353 
354  arg = argv[2];
355  argv++;
356  argc--;
357  }
358  else
359  arg += 2;
360 
361  out = fopen( arg, "wt" );
362  if ( out == NULL )
363  {
364  fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
365  exit(3);
366  }
367  break;
368 
369  case 'd':
370  if ( arg[2] == 0 )
371  {
372  if ( argc < 2 )
373  usage();
374 
375  arg = argv[2];
376  argv++;
377  argc--;
378  }
379  else
380  arg += 2;
381 
382  library_name = arg;
383  break;
384 
385  case 'w':
386  format = OUTPUT_WINDOWS_DEF;
387  switch ( arg[2] )
388  {
389  case 'B':
390  format = OUTPUT_BORLAND_DEF;
391  break;
392 
393  case 'W':
394  format = OUTPUT_WATCOM_LBC;
395  break;
396 
397  case 0:
398  break;
399 
400  default:
401  usage();
402  }
403  break;
404 
405  case 0:
406  from_stdin = 1;
407  break;
408 
409  default:
410  usage();
411  }
412 
413  argc--;
414  argv++;
415  }
416 
417  if ( from_stdin )
418  {
419  read_header_file( stdin, verbose );
420  }
421  else
422  {
423  for ( --argc, argv++; argc > 0; argc--, argv++ )
424  {
425  FILE* file = fopen( argv[0], "rb" );
426 
427  if ( file == NULL )
428  fprintf( stderr, "unable to open '%s'\n", argv[0] );
429  else
430  {
431  if ( verbose )
432  fprintf( stderr, "opening '%s'\n", argv[0] );
433 
434  read_header_file( file, verbose );
435  fclose( file );
436  }
437  }
438  }
439 
440  if ( num_names == 0 )
441  panic( "could not find exported functions !!\n" );
442 
443  names_sort();
444  names_dump( out, format, library_name );
445 
446  if ( out != stdout )
447  fclose( out );
448 
449  return 0;
450 }
#define PROGRAM_NAME
Definition: apinames.c:24
static void names_add(const char *name, const char *end)
Definition: apinames.c:59
static int name_compare(const void *name1, const void *name2)
Definition: apinames.c:108
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
int main(int argc, char **argv)
Definition: bootstrap.cpp:102
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
#define NULL
Definition: ftobjs.h:61
enum OutputFormat_ OutputFormat
FILE * file
Definition: visualinfo.c:88
EGLImageKHR EGLint * name
Definition: eglext.h:284
GLenum GLsizei len
Definition: glew.h:7035
#define PROGRAM_VERSION
Definition: apinames.c:25
static void names_sort(void)
Definition: apinames.c:118
OutputFormat_
Definition: apinames.c:29
struct NameRec_ * Name
static Name the_names
Definition: apinames.c:54
static int num_names
Definition: apinames.c:55
State_
Definition: apinames.c:201
int
Definition: SDL_systhread.c:37
static int max_names
Definition: apinames.c:56
GLfloat GLfloat p
Definition: glew.h:14938
#define realloc
Definition: SDL_malloc.c:637
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
enum State_ State
#define malloc
Definition: SDL_malloc.c:635
#define memcpy
Definition: SDL_malloc.c:634
static void panic(const char *message)
Definition: apinames.c:40
#define LINEBUFF_SIZE
Definition: apinames.c:27
GLuint GLuint end
Definition: glew.h:1239
static void names_dump(FILE *out, OutputFormat format, const char *dll_name)
Definition: apinames.c:126
int verbose
Definition: visualinfo.c:82
static int read_header_file(FILE *file, int verbose)
Definition: apinames.c:209
GLsizeiptr const GLvoid GLenum usage
Definition: glew.h:1667
struct NameRec_ NameRec
void qsort(void *base, size_t nmemb, size_t size, int(*compare)(const void *, const void *))
Definition: SDL_qsort.c:460