Flxcc Wrapper Generator

Felix now ships with flxcc which can be used to bulk generate wrappers for installed libraries. This tool is very much work in progress.

To execute, you should first install Felix. This is because the tool executes 'flxg', the Felix compiler, and it will use the one in the current PATH, not the development version.

Then use the command:

flxcc control_filename.flxcc

to execute the wrapper generator. When it finishes you can copy the generated wrappers and precompiled headers to where you want to install them, perhaps the

felix/lib

directory.

Flxcc control file format

The first thing you need to do is type

make default_wrappers

which copies a sample control file

config/usr_include.flxcc.default

to

config/usr_include.flxcc

where you can edit it without fear it will be clobbered by a new install. Examine the file and find some commands:

// comment
is a comment line and is ignored.

outdir flxcc_out
specifies the directory into which wrappers will be written.

prein usr_include.h
specifies the name of the C header file which flxcc generates.

preout usr_include.hhh
specifies the name of the preprocessed C header file which is generated by the C preprocessor

preprocessor gcc -E
specifies the preprocessor command to use to preprocess files.

path directory
adds a directory to the include path given to the preprocessor with a -I option

incfile filename.h
adds the regular C header file to the list of #include directives placed in the prein file.

incdir directory
adds all the regular files in the given directory to the list of #include directives placed in the prein file.

recincdir directory
adds all the regular files in the given directory, or any descendant thereof, to the list of #include directives placed in the prein file.

exclude filename
excludes a file or (for recincdir) a directory, from consideration as a file to #include in the prein file

Felix now generates the prein file, runs the preprocessor on it to generate the preout file. It then parses the preout file using the frontc/cil parser.

This creates an internal representation of the set of C headers included. Note that the headers represented are the transitive closure of the ones listed in the prein file: any of the files #included can #include other files.

merge filename1 filename2
This command tells flxcc to cheat, and pretend all definitions which occur in filename1 occur in filename2. This command must be used for internal implementation detail files such as GNU bits files which give an #error if included directly. Note that flxcc may still generate an empty module for such files even if the definitions have been merged into another file

noheader filename
tells flxcc not to generate a C #include for this file when it is generating the Felix wrapper. This command must be used for internal implementation detail files such as GNU bits files which give an #error if included directly.

rename sym1 sym2
tells flxcc to replace occurences of a Felix identifier sym1 with identifier sym2. This command is required to rename any symbol which happens to be a Felix keyword, but it can also be used to resolve other clashes with externally defined names. Note it cannot resolve any internal clashes since all occurences are renamed.

ignore sym1
tells flxcc to drop any definition of the specified symbol. This command is needed to prevent clashes with externally defined symbols such as standard library names. Uses of the symbol, however, are not affected, and so can map onto standard library names.

#include filename
tells flxcc to parse the denoted file for flxcc control statements.

Generated Output Example

// /usr/include/stdio.h
//Raw Input file: c89.hhh
//Generated by Felix Version 1.0.11
//Timestamp: 2004/9/30 4:38:48 UTC
//Timestamp: 2004/9/30 14:38:48 (local)
include 'std';

//#define __need_getopt
//#define fsetpos fsetpos64
//#define fgetpos fgetpos64
//#define ftello ftello64
//#define fseeko fseeko64
//#define putc(_ch, _fp) _IO_putc (_ch, _fp)
//#define getc(_fp) _IO_getc (_fp)
//#define freopen freopen64
//#define fopen fopen64
//#define tmpfile tmpfile64
//#define stderr stderr
//#define stdout stdout
//#define stdin stdin
//#define P_tmpdir      "/tmp"
//#define SEEK_END      2       /* Seek from end of file.  */
//#define SEEK_CUR      1       /* Seek from current position.  */
//#define SEEK_SET      0       /* Seek from beginning of file.  */
//#define EOF (-1)
//#define BUFSIZ _IO_BUFSIZ
//#define _IONBF 2              /* No buffering.  */
//#define _IOLBF 1              /* Line buffered.  */
//#define _IOFBF 0              /* Fully buffered.  */
//#define _VA_LIST_DEFINED
//#define _STDIO_USES_IOSTREAM
//#define ____FILE_defined      1
//#define __FILE_defined        1
//#define __need___FILE
//#define __need_FILE
//#define __need_NULL
//#define __need_size_t
//#define _STDIO_H      1
header '#include "/usr/include/stdio.h"';

//INCLUDES
include "_G_config_lib";
include "libio_lib";
include "stdarg_lib";

module stdio_h
{
  open C_hack;
  open _G_config_h;
  open libio_h;
  open stdarg_h;

  //EXTERNALLY COMPLETED TYPES
  //type _struct__IO_FILE defined in libio_h='/usr/include/libio.h';

  //STRUCT or UNION TAG ALIASES
  typedef FILE = _struct__IO_FILE;
  typedef __FILE = _struct__IO_FILE;

  //TYPE ALIASES
  typedef fpos_t = _G_fpos_t;

  //VARIABLES
  const stdout: ptr[_struct__IO_FILE] = 'stdout';
  const stderr: ptr[_struct__IO_FILE] = 'stderr';
  const stdin: ptr[_struct__IO_FILE] = 'stdin';

  //PROCEDURES
  proc clearerr: ptr[FILE] = ';';
  proc perror: cptr[char] = ';';
  proc rewind: ptr[FILE] = ';';
  proc setbuf: ptr[FILE] * ptr[char] = ';';

  //FUNCTIONS
  fun fclose: ptr[FILE] -> int;
  fun feof: ptr[FILE] -> int;
  fun ferror: ptr[FILE] -> int;
  fun fflush: ptr[FILE] -> int;
  fun fgetc: ptr[FILE] -> int;
  fun fgetpos: ptr[FILE] * ptr[fpos_t] -> int;
  fun fgets: ptr[char] * int * ptr[FILE] -> ptr[char];
  fun fopen: cptr[char] * cptr[char] -> ptr[FILE];
  fun fprintf[t]: t -> int = 'fprintf($a)';
  fun fputc: int * ptr[FILE] -> int;
  fun fputs: cptr[char] * ptr[FILE] -> int;
  fun fread: address * size * size * ptr[FILE] -> size;
  fun freopen: cptr[char] * cptr[char] * ptr[FILE] -> ptr[FILE];
  fun fscanf[t]: t -> int = 'fscanf($a)';
  fun fseek: ptr[FILE] * long * int -> int;
  fun fsetpos: ptr[FILE] * cptr[fpos_t] -> int;
  fun ftell: ptr[FILE] -> long;
  fun fwrite: caddress * size * size * ptr[FILE] -> size;
  fun getc: ptr[FILE] -> int;
  fun getchar: 1 -> int;
  fun gets: ptr[char] -> ptr[char];
  fun printf[t]: t -> int = 'printf($a)';
  fun putc: int * ptr[FILE] -> int;
  fun putchar: int -> int;
  fun puts: cptr[char] -> int;
  fun remove: cptr[char] -> int;
  fun rename_: cptr[char] * cptr[char] -> int = 'rename($a)';
  fun scanf[t]: t -> int = 'scanf($a)';
  fun setvbuf: ptr[FILE] * ptr[char] * int * size -> int;
  fun sprintf[t]: t -> int = 'sprintf($a)';
  fun sscanf[t]: t -> int = 'sscanf($a)';
  fun tmpfile: 1 -> ptr[FILE];
  fun tmpnam: ptr[char] -> ptr[char];
  fun ungetc: int * ptr[FILE] -> int;
  fun vfprintf: ptr[FILE] * cptr[char] * __gnuc_va_list -> int;
  fun vprintf: cptr[char] * __gnuc_va_list -> int;
  fun vsprintf: ptr[char] * cptr[char] * __gnuc_va_list -> int;
}