Table of Contents
OpenMCL uses an interface translation system based on the FFIGEN system (described here and here) to make the constant, type, structure, and function definitions in a set of .h files available to lisp code.
The basic idea of the FFIGEN scheme is to use the C compiler's frontend and parser to translate .h files into semantically equivalent .ffi files, which use an S-expression-based syntax to represent the definitions contained in those headers. Lisp code can then concentrate on the .ffi representation, without having to concern itself with the semantics of header file inclusion or the arcana of C parsing.
The original FFIGEN system used a modified version of the LCC C compiler to produce .ffi files. Since many LinuxPPC header files contain GCC-specific constructs, OpenMCL's translation system uses a modified version of GCC (called, somewhat confusingly, ffigen.)
A LinuxPPC binary is available at ftp://clozure.com/pub/ffigen-0.1.tar.gz, and LinuxPPC source differences are at ftp://clozure.com/pub/ffigen-src.tar.gz.
For Darwin, the binary is available at ftp://clozure.com/pub/ffigen-darwin.tar.gz, and the source differences are at ftp://clozure.com/pub/ffigen-darwin-src.tar.gz.
A shell script (distributed with the source and binary packages) called h-to-ffi.sh[1] reads a specified .h file (and optional preprocessor arguments) and writes a (hopefully) equivalent .ffi file to standard output, calling the installed C preprocessor and the ffigen program with appropriate arguments.
For each interface directory subdir distributed with OpenMCL, a shell script (distributed with OpenMCL as "ccl:headers;subdir;C;populate.sh" ("ccl:darwin-headers;subdir;C;populate.sh" for Darwin) calls h-to-ffi.sh on a large number of the header files in /usr/include (or some other system header path) and creates a parallel directory tree in "ccl:headers;subdir;C;system;header;path;" (or "ccl:darwin-headers;subdir;C;system;header;path;"), populating that directory with .ffi files.
A lisp function defined in "ccl:library;parse-ffi.lisp" reads the .ffi files in a specified interface directory subdir and generates new versions of the databases ("ccl:headers;subdir;constants.cdb", "ccl:headers;subdir;functions.cdb", "ccl:headers;subdir;records.cdb", and "ccl:headers;subdir;types.cdb")
The CDB databases are used by the #$ and #_ reader macros and are used in the expansion of RREF, RLET, and related macros.
Ensure that the FFIGEN program is installed. See the "README" file in the source or binary archive for specific installation instructions.
Edit the "ccl:headers;subdir;C;populate.sh" shell script. When you're confident that the files and preprocessor options match your environment, cd to the "ccl:headers;subdir;C;" directory and invoke ./populate.sh. Repeat this step until you're able to cleanly translate all files refrenced in the shell script.
Run OpenMCL:
? (require "PARSE-FFI") PARSE-FFI ? (parse-standard-ffi-files :SUBDIR) ;;; lots of output ... after a while, shiny new .cdb files should ;;; appear in "ccl:headers;subdir;" ;;; (or "ccl:darwin-headers;subdir;" under Darwin)
PARSE-STANDARD-FFI-FILES accepts a :PREPEND-UNDERSCORES keyword argument. Darwin (and some other platforms) use a convention wherein the symbols associated with C-visible external function and variables have underscore characters prepended to their names. When this argument is true, PARSE-STANDARD-FFI-FILES will prepend underscores to all foreign function names written to the database, so that (#_foo ...) expands into an EXTERNAL-CALL to "_foo".
[1] The ffigen program is a modified version of gcc 2.95; there have been changes in the protocol used to communicate between the C preprocessor and the compiler proper in gcc 3.x, and ffigen may not understand preprocessor output from later versions of the preprocessor.
OSX 10.2 installs gcc 3.1 as the default version of gcc; gcc 2.95 continues to be available as “gcc2”. Linux distributions generally do something similar. The “h-to-ffi.sh” shell script invokes the preprocessor by calling “gcc” with appropriate options; this may cause the “wrong” version of the preprocessor to be invoked.
A simple workaround is to edit the “h-to-ffi.sh” script so that its PREPROCESS variable invokes gcc 2.95. Under Jaguar, this involves changing “gcc” to “gcc2”.