ReactOS  0.4.14-dev-606-g14ebc0b
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-2013, 2015
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.2"
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  OUTPUT_NETWARE_IMP /* output a NetWare ImportFile */
36 
37 } OutputFormat;
38 
39 
40 static void
41 panic( const char* message )
42 {
43  fprintf( stderr, "PANIC: %s\n", message );
44  exit(2);
45 }
46 
47 
48 typedef struct NameRec_
49 {
50  char* name;
51  unsigned int hash;
52 
53 } NameRec, *Name;
54 
55 static Name the_names;
56 static int num_names;
57 static int max_names;
58 
59 static void
60 names_add( const char* name,
61  const char* end )
62 {
63  unsigned int h;
64  int nn, len;
65  Name nm;
66 
67  if ( end <= name )
68  return;
69 
70  /* compute hash value */
71  len = (int)(end - name);
72  h = 0;
73  for ( nn = 0; nn < len; nn++ )
74  h = h*33 + name[nn];
75 
76  /* check for an pre-existing name */
77  for ( nn = 0; nn < num_names; nn++ )
78  {
79  nm = the_names + nn;
80 
81  if ( (int)nm->hash == h &&
82  memcmp( name, nm->name, len ) == 0 &&
83  nm->name[len] == 0 )
84  return;
85  }
86 
87  /* add new name */
88  if ( num_names >= max_names )
89  {
90  max_names += (max_names >> 1) + 4;
92  sizeof ( the_names[0] ) * max_names );
93  if ( !the_names )
94  panic( "not enough memory" );
95  }
96  nm = &the_names[num_names++];
97 
98  nm->hash = h;
99  nm->name = (char*)malloc( len+1 );
100  if ( !nm->name )
101  panic( "not enough memory" );
102 
103  memcpy( nm->name, name, len );
104  nm->name[len] = 0;
105 }
106 
107 
108 static int
109 name_compare( const void* name1,
110  const void* name2 )
111 {
112  Name n1 = (Name)name1;
113  Name n2 = (Name)name2;
114 
115  return strcmp( n1->name, n2->name );
116 }
117 
118 static void
119 names_sort( void )
120 {
121  qsort( the_names, (size_t)num_names,
122  sizeof ( the_names[0] ), name_compare );
123 }
124 
125 
126 static void
129  const char* dll_name )
130 {
131  int nn;
132 
133 
134  switch ( format )
135  {
136  case OUTPUT_WINDOWS_DEF:
137  if ( dll_name )
138  fprintf( out, "LIBRARY %s\n", dll_name );
139 
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 );
144  break;
145 
146  case OUTPUT_BORLAND_DEF:
147  if ( dll_name )
148  fprintf( out, "LIBRARY %s\n", dll_name );
149 
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 );
154  break;
155 
156  case OUTPUT_WATCOM_LBC:
157  {
158  const char* dot;
159  char temp[512];
160 
161 
162  if ( !dll_name )
163  {
164  fprintf( stderr,
165  "you must provide a DLL name with the -d option!\n" );
166  exit( 4 );
167  }
168 
169  /* we must omit the .dll suffix from the library name */
170  dot = strchr( dll_name, '.' );
171  if ( dot )
172  {
173  int len = dot - dll_name;
174 
175 
176  if ( len > (int)( sizeof ( temp ) - 1 ) )
177  len = sizeof ( temp ) - 1;
178 
179  memcpy( temp, dll_name, len );
180  temp[len] = 0;
181 
182  dll_name = (const char*)temp;
183  }
184 
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 );
188  }
189  break;
190 
191  case OUTPUT_NETWARE_IMP:
192  {
193  if ( dll_name )
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 );
198  }
199  break;
200 
201  default: /* LIST */
202  for ( nn = 0; nn < num_names; nn++ )
203  fprintf( out, "%s\n", the_names[nn].name );
204  }
205 }
206 
207 
208 
209 
210 /* states of the line parser */
211 
212 typedef enum State_
213 {
214  STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
215  STATE_TYPE /* type was read, waiting for function name */
216 
217 } State;
218 
219 static int
221 {
222  static char buff[LINEBUFF_SIZE + 1];
224 
225  while ( !feof( file ) )
226  {
227  char* p;
228 
229  if ( !fgets( buff, LINEBUFF_SIZE, file ) )
230  break;
231 
232  p = buff;
233 
234  while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
235  p++;
236 
237  if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
238  continue;
239 
240  switch ( state )
241  {
242  case STATE_START:
243  {
244  if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
245  break;
246 
247  p += 10;
248  for (;;)
249  {
250  if ( *p == 0 || *p == '\n' || *p == '\r' )
251  goto NextLine;
252 
253  if ( *p == ')' )
254  {
255  p++;
256  break;
257  }
258 
259  p++;
260  }
261 
262  state = STATE_TYPE;
263 
264  /* sometimes, the name is just after the FT_EXPORT(...), so
265  * skip whitespace, and fall-through if we find an alphanumeric
266  * character
267  */
268  while ( *p == ' ' || *p == '\t' )
269  p++;
270 
271  if ( !isalpha(*p) )
272  break;
273  }
274  /* fall-through */
275 
276  case STATE_TYPE:
277  {
278  char* name = p;
279 
280  while ( isalnum(*p) || *p == '_' )
281  p++;
282 
283  if ( p > name )
284  {
285  if ( verbose )
286  fprintf( stderr, ">>> %.*s\n", (int)(p - name), name );
287 
288  names_add( name, p );
289  }
290 
291  state = STATE_START;
292  }
293  break;
294 
295  default:
296  ;
297  }
298 
299  NextLine:
300  ;
301  }
302 
303  return 0;
304 }
305 
306 
307 static void
308 usage( void )
309 {
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"
315 
316  "usage: %s header1 [options] [header2 ...]\n\n"
317 
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"
326  "\n";
327 
328  fprintf( stderr,
329  format,
330  PROGRAM_NAME,
333  );
334  exit(1);
335 }
336 
337 
338 int main( int argc, const char* const* argv )
339 {
340  int from_stdin = 0;
341  int verbose = 0;
342  OutputFormat format = OUTPUT_LIST; /* the default */
343  FILE* out = stdout;
344  const char* library_name = NULL;
345 
346  if ( argc < 2 )
347  usage();
348 
349  /* '-' used as a single argument means read source file from stdin */
350  while ( argc > 1 && argv[1][0] == '-' )
351  {
352  const char* arg = argv[1];
353 
354  switch ( arg[1] )
355  {
356  case 'v':
357  verbose = 1;
358  break;
359 
360  case 'o':
361  if ( arg[2] == 0 )
362  {
363  if ( argc < 2 )
364  usage();
365 
366  arg = argv[2];
367  argv++;
368  argc--;
369  }
370  else
371  arg += 2;
372 
373  out = fopen( arg, "wt" );
374  if ( !out )
375  {
376  fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
377  exit(3);
378  }
379  break;
380 
381  case 'd':
382  if ( arg[2] == 0 )
383  {
384  if ( argc < 2 )
385  usage();
386 
387  arg = argv[2];
388  argv++;
389  argc--;
390  }
391  else
392  arg += 2;
393 
394  library_name = arg;
395  break;
396 
397  case 'w':
399  switch ( arg[2] )
400  {
401  case 'B':
403  break;
404 
405  case 'W':
407  break;
408 
409  case 'N':
411  break;
412 
413  case 0:
414  break;
415 
416  default:
417  usage();
418  }
419  break;
420 
421  case 0:
422  from_stdin = 1;
423  break;
424 
425  default:
426  usage();
427  }
428 
429  argc--;
430  argv++;
431  }
432 
433  if ( from_stdin )
434  {
436  }
437  else
438  {
439  for ( --argc, argv++; argc > 0; argc--, argv++ )
440  {
441  FILE* file = fopen( argv[0], "rb" );
442 
443  if ( !file )
444  fprintf( stderr, "unable to open '%s'\n", argv[0] );
445  else
446  {
447  if ( verbose )
448  fprintf( stderr, "opening '%s'\n", argv[0] );
449 
451  fclose( file );
452  }
453  }
454  }
455 
456  if ( num_names == 0 )
457  panic( "could not find exported functions !!\n" );
458 
459  names_sort();
460  names_dump( out, format, library_name );
461 
462  if ( out != stdout )
463  fclose( out );
464 
465  return 0;
466 }
#define realloc
Definition: debug_ros.c:6
#define PROGRAM_NAME
Definition: apinames.c:24
static void names_add(const char *name, const char *end)
Definition: apinames.c:60
static int argc
Definition: ServiceArgs.c:12
Definition: tftpd.h:59
static int name_compare(const void *name1, const void *name2)
Definition: apinames.c:109
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
unsigned int hash
Definition: apinames.c:51
int main(int argc, const char *const *argv)
Definition: apinames.c:338
enum OutputFormat_ OutputFormat
#define isalpha(c)
Definition: acclib.h:74
FILE * stdin
void * arg
Definition: msvc.h:10
GLuint GLuint end
Definition: gl.h:1545
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
#define argv
Definition: mplay32.c:18
static WCHAR name1[]
Definition: record.c:34
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
FILE * stdout
#define PROGRAM_VERSION
Definition: apinames.c:25
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
#define verbose
Definition: rosglue.h:36
static void names_sort(void)
Definition: apinames.c:119
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
struct NameRec_ * Name
Definition: cdprocs.h:464
OutputFormat_
Definition: apinames.c:29
smooth NULL
Definition: ftsmooth.c:416
static Name the_names
Definition: apinames.c:55
static int num_names
Definition: apinames.c:56
State_
Definition: apinames.c:212
_Check_return_ _CRTIMP int __cdecl feof(_In_ FILE *_File)
static int max_names
Definition: apinames.c:57
static FILE * out
Definition: regtests2xml.c:44
int n1
Definition: dwarfget.c:148
char * name
Definition: apinames.c:50
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
static void usage(void)
Definition: apinames.c:308
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
enum State_ State
Definition: pofuncs.h:54
int n2
Definition: dwarfget.c:148
static void panic(const char *message)
Definition: apinames.c:41
static calc_node_t temp
Definition: rpn_ieee.c:38
#define LINEBUFF_SIZE
Definition: apinames.c:27
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static void names_dump(FILE *out, OutputFormat format, const char *dll_name)
Definition: apinames.c:127
Definition: name.c:38
FILE * stderr
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
static int read_header_file(FILE *file, int verbose)
Definition: apinames.c:220
static WCHAR name2[]
Definition: record.c:35
#define malloc
Definition: debug_ros.c:4
void exit(int exitcode)
Definition: _exit.c:33
GLfloat GLfloat p
Definition: glext.h:8902
struct NameRec_ NameRec
static unsigned char buff[32768]
Definition: fatten.c:17
BOOLEAN NextLine
Definition: bootvid.c:28
STATE_TYPE
Definition: effect.c:95
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
Definition: fci.c:126