mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-20 14:19:18 +02:00
Renaming tools, adding -c option to automatically compile with chibi-ffi.
This commit is contained in:
parent
2cd95a04d3
commit
13cf6d24d5
5 changed files with 68 additions and 564 deletions
11
Makefile
11
Makefile
|
@ -1,6 +1,6 @@
|
||||||
# -*- makefile-gmake -*-
|
# -*- makefile-gmake -*-
|
||||||
|
|
||||||
.PHONY: all libs doc dist clean cleaner dist-clean install uninstall test checkdefs
|
.PHONY: all libs dist clean cleaner dist-clean install uninstall test checkdefs
|
||||||
.PRECIOUS: %.c
|
.PRECIOUS: %.c
|
||||||
|
|
||||||
# install configuration
|
# install configuration
|
||||||
|
@ -17,8 +17,8 @@ MANDIR ?= $(PREFIX)/share/man/man1
|
||||||
|
|
||||||
DESTDIR ?=
|
DESTDIR ?=
|
||||||
|
|
||||||
GENSTUBS ?= ./tools/genstubs.scm
|
GENSTUBS ?= ./tools/chibi-ffi
|
||||||
GENSTATIC ?= ./tools/genstatic.scm
|
GENSTATIC ?= ./tools/chibi-genstatic
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# system configuration - if not using GNU make, set PLATFORM and the
|
# system configuration - if not using GNU make, set PLATFORM and the
|
||||||
|
@ -165,7 +165,7 @@ lib/chibi/ast$(SO): lib/chibi/ast.c $(INCLUDES)
|
||||||
lib/%$(SO): lib/%.c $(INCLUDES)
|
lib/%$(SO): lib/%.c $(INCLUDES)
|
||||||
-$(CC) $(CLIBFLAGS) $(XCPPFLAGS) $(XCFLAGS) -o $@ $< -L. -lchibi-scheme
|
-$(CC) $(CLIBFLAGS) $(XCPPFLAGS) $(XCFLAGS) -o $@ $< -L. -lchibi-scheme
|
||||||
|
|
||||||
%.html: %.scrbl tools/chibi-doc
|
%.html: %.scrbl tools/chibi-doc chibi-scheme$(EXE)
|
||||||
$(CHIBI) tools/chibi-doc $< > $@
|
$(CHIBI) tools/chibi-doc $< > $@
|
||||||
|
|
||||||
doc: doc/chibi.html
|
doc: doc/chibi.html
|
||||||
|
@ -240,7 +240,8 @@ test: chibi-scheme$(EXE)
|
||||||
install: chibi-scheme$(EXE)
|
install: chibi-scheme$(EXE)
|
||||||
mkdir -p $(DESTDIR)$(BINDIR)
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
cp chibi-scheme$(EXE) $(DESTDIR)$(BINDIR)/
|
cp chibi-scheme$(EXE) $(DESTDIR)$(BINDIR)/
|
||||||
cp tools/genstubs.scm $(DESTDIR)$(BINDIR)/
|
cp tools/chibi-ffi $(DESTDIR)$(BINDIR)/
|
||||||
|
cp tools/chibi-doc $(DESTDIR)$(BINDIR)/
|
||||||
mkdir -p $(DESTDIR)$(MODDIR)
|
mkdir -p $(DESTDIR)$(MODDIR)
|
||||||
cp -r lib/* $(DESTDIR)$(MODDIR)/
|
cp -r lib/* $(DESTDIR)$(MODDIR)/
|
||||||
mkdir -p $(DESTDIR)$(INCDIR)
|
mkdir -p $(DESTDIR)$(INCDIR)
|
||||||
|
|
449
README
449
README
|
@ -6,435 +6,20 @@
|
||||||
|
|
||||||
http://synthcode.com/wiki/chibi-scheme/
|
http://synthcode.com/wiki/chibi-scheme/
|
||||||
|
|
||||||
|
Chibi-Scheme is a very small library intended for use as an extension
|
||||||
Chibi-Scheme is a very small but mostly complete R5RS Scheme
|
and scripting language in C programs. In addition to support for
|
||||||
implementation using a reasonably fast custom VM. Chibi-Scheme tries
|
lightweight VM-based threads, each VM itself runs in an isolated heap
|
||||||
as much as possible not to trade its small size by cutting corners,
|
allowing multiple VMs to run simultaneously in different OS threads.
|
||||||
and provides full continuations, both low and high-level hygienic
|
|
||||||
macros based on syntactic-closures, string ports and exceptions.
|
The default language is R5RS Scheme with support for additional
|
||||||
Chibi-Scheme is written in highly portable C and supports multiple
|
languages such as JavaScript to be provided in future releases.
|
||||||
simultaneous VM instances to run.
|
Scheme is chosen as a substrate because its first class continuations
|
||||||
|
and guaranteed tail-call optimization makes implementing other
|
||||||
------------------------------------------------------------------------
|
languages easy.
|
||||||
INSTALLING
|
|
||||||
|
To build on most platforms just run "make". This will provide a
|
||||||
To build, just run "make". This will provide a shared library
|
shared library "libchibi-scheme", as well as a sample "chibi-scheme"
|
||||||
"libchibi-scheme", as well as a sample "chibi-scheme" command-line
|
command-line repl.
|
||||||
repl. The "chibi-scheme-static" make target builds an equivalent
|
|
||||||
static executable.
|
For more detailed documentation, run "make doc" and see the generated
|
||||||
|
"doc/chibi.html".
|
||||||
You can edit the file chibi/features.h for a number of settings,
|
|
||||||
mostly disabling features to make the executable smaller. You can
|
|
||||||
specify standard options directly as arguments to make, for example
|
|
||||||
|
|
||||||
make CFLAGS=-Os CPPFLAGS=-DSEXP_USE_NO_FEATURES=1
|
|
||||||
|
|
||||||
to optimize for size, or
|
|
||||||
|
|
||||||
make LDFLAGS=-L/usr/local/lib CPPFLAGS=-I/usr/local/include
|
|
||||||
|
|
||||||
to compile against a library installed in /usr/local.
|
|
||||||
|
|
||||||
By default Chibi uses a custom, precise, non-moving GC. You can link
|
|
||||||
against the Boehm conservative GC by editing the features.h file, or
|
|
||||||
directly from make with:
|
|
||||||
|
|
||||||
make SEXP_USE_BOEHM=1
|
|
||||||
|
|
||||||
To compile a static executable, use
|
|
||||||
|
|
||||||
make chibi-scheme-static SEXP_USE_DL=0
|
|
||||||
|
|
||||||
To compile a static executable with all C libraries statically
|
|
||||||
included, first you need to create a clibs.c file, which can be done
|
|
||||||
with:
|
|
||||||
|
|
||||||
make clibs.c
|
|
||||||
|
|
||||||
or edited manually. Be sure to run this with a non-static
|
|
||||||
chibi-scheme. Then you can make the static executable with:
|
|
||||||
|
|
||||||
make cleaner
|
|
||||||
make chibi-scheme-static SEXP_USE_DL=0 CPPFLAGS=-DSEXP_USE_STATIC_LIBS
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
CHIBI-SCHEME LANGUAGE
|
|
||||||
|
|
||||||
The default language is mostly compatible with the R5RS, with all
|
|
||||||
differences made by design, not through difficulty of implementation.
|
|
||||||
The following procedures are omitted:
|
|
||||||
|
|
||||||
transcript-on and transcript-off (because they're silly)
|
|
||||||
rationalize (pending the addition of rational numbers)
|
|
||||||
|
|
||||||
Apart from this, chibi-scheme is case-sensitive, unlike the R5RS.
|
|
||||||
The default configuration includes fixnums, flonums and bignums
|
|
||||||
but no exact rationals or complex numbers.
|
|
||||||
|
|
||||||
Full continuations are supported, but currently continuations don't
|
|
||||||
take C code into account. The only higher-order C functions in the
|
|
||||||
standard environment are LOAD and EVAL.
|
|
||||||
|
|
||||||
LOAD is extended to accept an optional environment argument, like
|
|
||||||
EVAL. You can also LOAD shared libraries in addition to Scheme source
|
|
||||||
files - in this case the function sexp_init_library is automatically
|
|
||||||
called with the following signature:
|
|
||||||
|
|
||||||
sexp_init_library(sexp context, sexp environment)
|
|
||||||
|
|
||||||
SYNTAX-RULES macros are provided by default, with the extensions from
|
|
||||||
SRFI-46. In addition, low-level hygienic macros are provided with
|
|
||||||
a syntactic-closures interface, including SC-MACRO-TRANSFORMER,
|
|
||||||
RSC-MACRO-TRANSFORMER, and ER-MACRO-TRANSFORMER. A good introduction
|
|
||||||
to syntactic-closures can be found at:
|
|
||||||
|
|
||||||
http://community.schemewiki.org/?syntactic-closures
|
|
||||||
|
|
||||||
IDENTIFIER?, IDENTIFIER->SYMBOL, IDENTIFIER=?, and
|
|
||||||
MAKE-SYNTACTIC-CLOSURE and STRIP-SYNTACTIC-CLOSURES are provided.
|
|
||||||
|
|
||||||
SRFI-0's COND-EXPAND is provided, with the feature `chibi'.
|
|
||||||
|
|
||||||
STRING-CONCATENATE concatenates a list of strings.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
TYPES
|
|
||||||
|
|
||||||
You can define new data types with SRFI-9. This is just syntactic
|
|
||||||
sugar for the following more primitive type constructors:
|
|
||||||
|
|
||||||
(register-simple-type <name-string> <num-fields>)
|
|
||||||
=> <type-id> ; a fixnum
|
|
||||||
|
|
||||||
(make-type-predicate <opcode-name-string> <type-id>)
|
|
||||||
=> <opcode> ; takes 1 arg, returns #t iff that arg is of the type
|
|
||||||
|
|
||||||
(make-constructor <constructor-name-string> <type-id>)
|
|
||||||
=> <opcode> ; takes 0 args, returns a newly allocated instance of type
|
|
||||||
|
|
||||||
(make-getter <getter-name-string> <type-id> <field-index>)
|
|
||||||
=> <opcode> ; takes 1 args, retrieves the field located at the index
|
|
||||||
|
|
||||||
(make-setter <setter-name-string> <type-id> <field-index>)
|
|
||||||
=> <opcode> ; takes 2 args, sets the field located at the index
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
MODULE SYSTEM
|
|
||||||
|
|
||||||
A configurable module system, in the style of the Scheme48 module
|
|
||||||
system, is provided by default.
|
|
||||||
|
|
||||||
Modules names are hierarchical lists of symbols or numbers. The
|
|
||||||
definition of the module (foo bar baz) is searched for in the file
|
|
||||||
foo/bar/baz.module. This file should contain an expression of the
|
|
||||||
form:
|
|
||||||
|
|
||||||
(define-module (foo bar baz)
|
|
||||||
<module-declarations> ...)
|
|
||||||
|
|
||||||
where <module-declarations> can be any of
|
|
||||||
|
|
||||||
(export <id> ...) - specify an export list
|
|
||||||
(import <import-spec> ...) - specify one or more imports
|
|
||||||
(import-immutable <import-spec> ...) - specify an immutable import
|
|
||||||
(body <expr> ...) - inline Scheme code
|
|
||||||
(include <file> ...) - load one or more files
|
|
||||||
(include-shared <file> ...) - dynamic load a library
|
|
||||||
|
|
||||||
<import-spec> can either be a module name or any of
|
|
||||||
|
|
||||||
(only <import-spec> <id> ...)
|
|
||||||
(except <import-spec> <id> ...)
|
|
||||||
(rename <import-spec> (<from-id> <to-id>) ...)
|
|
||||||
(prefix <prefix-id> <import-spec>)
|
|
||||||
|
|
||||||
The can be composed and perform basic selection and renaming of
|
|
||||||
individual identifiers from the given module.
|
|
||||||
|
|
||||||
Files are loaded relative to the .module file, and are written with
|
|
||||||
their extension (so you can use whatever suffix you prefer - .scm,
|
|
||||||
.ss, .sls, etc.).
|
|
||||||
|
|
||||||
Shared modules, on the other hand, should be specified _without_ the
|
|
||||||
extension - the correct suffix will be added portably (e.g. .so for
|
|
||||||
Unix and .dylib for OS X).
|
|
||||||
|
|
||||||
You may also use COND-EXPAND and arbitrary macro expansions in a
|
|
||||||
module definition to generate <module-declarations>.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
MODULES
|
|
||||||
|
|
||||||
The default environment is (scheme) - you almost always want to import
|
|
||||||
this.
|
|
||||||
|
|
||||||
Currently you can load the following SRFIs with (import (srfi N)):
|
|
||||||
|
|
||||||
(srfi 0) - cond-expand
|
|
||||||
(srfi 1) - list library
|
|
||||||
(srfi 2) - and-let*
|
|
||||||
(srfi 6) - basic string ports
|
|
||||||
(srfi 8) - receive
|
|
||||||
(srfi 9) - define-record-type
|
|
||||||
(srfi 11) - let-values/let*-values
|
|
||||||
(srfi 16) - case-lambda
|
|
||||||
(srfi 22) - running scheme scripts on Unix
|
|
||||||
(srfi 23) - error reporting mechanism
|
|
||||||
(srfi 26) - cut/cute partial application
|
|
||||||
(srfi 27) - sources of random bits
|
|
||||||
(srfi 33) - bitwise operators
|
|
||||||
(srfi 39) - prameter objects
|
|
||||||
(srfi 46) - basic syntax-rules extensions
|
|
||||||
(srfi 62) - s-expression comments
|
|
||||||
(srfi 69) - basic hash tables
|
|
||||||
(srfi 95) - sorting and merging
|
|
||||||
(srfi 98) - environment access
|
|
||||||
|
|
||||||
although 0, 22, 23, 46 and 62 are built into the default environment
|
|
||||||
so there's no need to import them.
|
|
||||||
|
|
||||||
Included non-standard modules are put in the (chibi) module namespace.
|
|
||||||
The following additional modules are available:
|
|
||||||
|
|
||||||
(chibi net) - networking interface
|
|
||||||
(chibi filesystem) - local filesystem and file descriptor interface
|
|
||||||
(chibi process) - processes and signals
|
|
||||||
(chibi system) - host system and user information
|
|
||||||
(chibi time) - time and date library
|
|
||||||
(chibi match) - pattern-matching library
|
|
||||||
(chibi loop) - extensible loop syntax
|
|
||||||
(chibi pathname) - pathname manipulation utilities
|
|
||||||
(chibi uri) - URI parsing and construction utilities
|
|
||||||
(chibi macroexpand) - macro expansion utility
|
|
||||||
(chibi ast) - interface to the internal Abstract Syntax Tree
|
|
||||||
(chibi disasm) - disassembly utility for the chibi VM
|
|
||||||
(chibi heap-stats) - debugging tool to analyze or dump the heap
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
C INTERFACE
|
|
||||||
|
|
||||||
See the file main.c for an example of using chibi-scheme as a library.
|
|
||||||
|
|
||||||
The basic usage involves creating a context for evaluation and loading
|
|
||||||
or evaluating Scheme source with it. Begin by including the eval.h
|
|
||||||
header file:
|
|
||||||
|
|
||||||
#include <chibi/eval.h>
|
|
||||||
|
|
||||||
then call
|
|
||||||
|
|
||||||
sexp_scheme_init();
|
|
||||||
|
|
||||||
with no parameters to initialize any globals (this actually does
|
|
||||||
nothing in the standard configuration but is a good idea to call
|
|
||||||
anyway).
|
|
||||||
|
|
||||||
Then you can use the following to create and manipulate contexts:
|
|
||||||
|
|
||||||
sexp_make_eval_context(context, stack, environment, heap_size)
|
|
||||||
Creates a new context with the given stack and environment.
|
|
||||||
If context is non-NULL, this will be the "parent" context and
|
|
||||||
the two contexts will share a heap. Otherwise, a new heap
|
|
||||||
will be allocated with heap_size, or a default size if heap_size
|
|
||||||
is zero. stack and environment may both also be NULL (and _must_
|
|
||||||
be NULL if context is NULL) and will be given standard defaults.
|
|
||||||
|
|
||||||
Thus to create your first context you generally call:
|
|
||||||
|
|
||||||
sexp_make_eval_context(NULL, NULL, NULL, 0)
|
|
||||||
|
|
||||||
You can create as many contexts as you want, and other than those
|
|
||||||
sharing a heap they are all independent and thread-safe.
|
|
||||||
|
|
||||||
sexp_load_standard_env(context, env, version)
|
|
||||||
Loads the init.scm file in the environment env. Version refers
|
|
||||||
to the RnRS version number and should always be SEXP_FIVE. The
|
|
||||||
environment created with sexp_make_eval_context only contains
|
|
||||||
core syntactic forms and C primitives (thus for example it has
|
|
||||||
CAR but not CADR or LIST), so to get a full featured
|
|
||||||
environment, plus a module system with which to load additional
|
|
||||||
modules, you want to use this.
|
|
||||||
|
|
||||||
sexp_destroy_context(context)
|
|
||||||
Signals that you no longer need context, or any other context
|
|
||||||
sharing the heap. It will thus free() the context and heap and
|
|
||||||
all associated memory. Does nothing if using the Boehm GC.
|
|
||||||
|
|
||||||
Environments can be handled with the following:
|
|
||||||
|
|
||||||
sexp_context_env(context)
|
|
||||||
A macro returning the default environment associated with context.
|
|
||||||
|
|
||||||
sexp_env_define(context, env, symbol, value)
|
|
||||||
Define a variable in an environment.
|
|
||||||
|
|
||||||
sexp_env_ref(env, symbol, dflt)
|
|
||||||
Fetch the binding for symbol from the environment env,
|
|
||||||
returning the default dflt if the symbol is unbound.
|
|
||||||
|
|
||||||
You can evaluate code with the following utility:
|
|
||||||
|
|
||||||
sexp_eval(context, expr, env)
|
|
||||||
Evaluates an s-expression in an environment.
|
|
||||||
env can be NULL to use the context's default env.
|
|
||||||
|
|
||||||
sexp_eval_string(context, str, env)
|
|
||||||
Reads an s-expression from str and evaluates it in env.
|
|
||||||
|
|
||||||
sexp_load(context, file, env)
|
|
||||||
Read and eval all top-level forms from file in environment env.
|
|
||||||
As described in LOAD above, file may be a shared library.
|
|
||||||
|
|
||||||
To define new primitive functions from C, use sexp_define_foreign,
|
|
||||||
which takes a Scheme environment, a name, a number of arguments the C
|
|
||||||
function takes (not counting the context argument), and a C function.
|
|
||||||
|
|
||||||
/* sexp_define_foreign(context, env, name, num_args, f) */
|
|
||||||
|
|
||||||
sexp add (sexp context, sexp x, sexp y) {
|
|
||||||
return sexp_fx_add(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
sexp_define_foreign(context, env, "add", 2, add);
|
|
||||||
|
|
||||||
You can also define functions with a single optional argument:
|
|
||||||
|
|
||||||
sexp_define_foreign_opt(context, env, "add", 2, add, sexp_make_fixnum(1));
|
|
||||||
|
|
||||||
See the SRFI-69 implementation for more detailed examples of this.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
FFI
|
|
||||||
|
|
||||||
Simple C FFI. "genstubs.scm file.stub" will read in the C function
|
|
||||||
FFI definitions from file.stub and output the appropriate C
|
|
||||||
wrappers into file.c. You can then compile that file with:
|
|
||||||
|
|
||||||
cc -fPIC -shared file.c -lchibi-scheme
|
|
||||||
|
|
||||||
(or using whatever flags are appropriate to generate shared libs on
|
|
||||||
your platform) and then the generated .so file can be loaded
|
|
||||||
directly with LOAD, or portably using (include-shared "file") in a
|
|
||||||
module definition (note that include-shared uses no suffix).
|
|
||||||
|
|
||||||
The goal of this interface is to make access to C types and
|
|
||||||
functions easy, without requiring the user to write any C code.
|
|
||||||
That means the stubber needs to be intelligent about various C
|
|
||||||
calling conventions and idioms, such as return values passed in
|
|
||||||
actual parameters. Writing C by hand is still possible, and
|
|
||||||
several of the core modules provide C interfaces directly without
|
|
||||||
using the stubber.
|
|
||||||
|
|
||||||
================================
|
|
||||||
|
|
||||||
Struct Interface
|
|
||||||
|
|
||||||
(define-c-struct struct-name
|
|
||||||
[predicate: predicate-name]
|
|
||||||
[constructor: constructor-name]
|
|
||||||
[finalizer: c_finalizer_name]
|
|
||||||
(type c_field_name getter-name setter-name) ...)
|
|
||||||
|
|
||||||
|
|
||||||
================================
|
|
||||||
|
|
||||||
|
|
||||||
Function Interface
|
|
||||||
|
|
||||||
(define-c return-type name-spec (arg-type ...))
|
|
||||||
|
|
||||||
where name-space is either a symbol name, or a list of
|
|
||||||
(scheme-name c_name). If just a symbol, the C name is taken
|
|
||||||
to be the same with -'s replaced by _'s.
|
|
||||||
|
|
||||||
arg-type is a type suitable for input validation and conversion.
|
|
||||||
|
|
||||||
================================
|
|
||||||
|
|
||||||
|
|
||||||
Types
|
|
||||||
|
|
||||||
Types
|
|
||||||
|
|
||||||
Basic Types
|
|
||||||
void
|
|
||||||
boolean
|
|
||||||
char
|
|
||||||
sexp (no conversions)
|
|
||||||
|
|
||||||
Integer Types:
|
|
||||||
signed-char short int long
|
|
||||||
unsigned-char unsigned-short unsigned-int unsigned-long size_t pid_t
|
|
||||||
time_t (in seconds, but using the chibi epoch of 2010/01/01)
|
|
||||||
errno (as a return type returns #f on error)
|
|
||||||
|
|
||||||
Float Types:
|
|
||||||
float double long-double
|
|
||||||
|
|
||||||
String Types:
|
|
||||||
string - a null-terminated char*
|
|
||||||
env-string - a VAR=VALUE string represented as a (VAR . VALUE) pair inScheme
|
|
||||||
in addition you can use (array char) as a string
|
|
||||||
|
|
||||||
Port Types:
|
|
||||||
input-port output-port
|
|
||||||
|
|
||||||
Struct Types:
|
|
||||||
|
|
||||||
Struct types are by default just referred to by the bare
|
|
||||||
struct-name from define-c-struct, and it is assumed you want a
|
|
||||||
pointer to that type. To refer to the full struct, use the struct
|
|
||||||
modifier, as in (struct struct-name).
|
|
||||||
|
|
||||||
Type modifiers
|
|
||||||
|
|
||||||
Any type may also be written as a list of modifiers followed by the
|
|
||||||
type itself. The supported modifiers are:
|
|
||||||
|
|
||||||
const: prepends the "const" C type modifier
|
|
||||||
* as a return or result parameter, makes non-immediates immutable
|
|
||||||
|
|
||||||
free: it's Scheme's responsibility to "free" this resource
|
|
||||||
* as a return or result parameter, registers the freep flag
|
|
||||||
this causes the type finalizer to be run when GCed
|
|
||||||
|
|
||||||
maybe-null: this pointer type may be NULL
|
|
||||||
* as a result parameter, NULL is translated to #f
|
|
||||||
normally this would just return a wrapped NULL pointer
|
|
||||||
* as an input parameter, #f is translated to NULL
|
|
||||||
normally this would be a type error
|
|
||||||
|
|
||||||
pointer: create a pointer to this type
|
|
||||||
* as a return parameter, wraps the result in a vanilla cpointer
|
|
||||||
* as a result parameter, boxes then unboxes the value
|
|
||||||
|
|
||||||
struct: treat this struct type as a struct, not a pointer
|
|
||||||
* as an input parameter, dereferences the pointer
|
|
||||||
* as a type field, indicates a nested struct
|
|
||||||
|
|
||||||
link: add a gc link
|
|
||||||
* as a field getter, link to the parent object, so the
|
|
||||||
parent won't be GCed so long as we have a reference
|
|
||||||
to the child. this behavior is automatic for nested
|
|
||||||
structs.
|
|
||||||
|
|
||||||
result: return a result in this parameter
|
|
||||||
* if there are multiple results (including the return type),
|
|
||||||
they are all returned in a list
|
|
||||||
* if there are any result parameters, a return type
|
|
||||||
of errno returns #f on failure, and as eliminated
|
|
||||||
from the list of results otherwise
|
|
||||||
|
|
||||||
(value <expr>): specify a fixed value
|
|
||||||
* as an input parameter, this parameter is not provided
|
|
||||||
in the Scheme API but always passed as <expr>
|
|
||||||
|
|
||||||
(default <expr>): specify a default value
|
|
||||||
* as the final input parameter, makes the Scheme parameter
|
|
||||||
optional, defaulting to <expr>
|
|
||||||
|
|
||||||
(array <type> [<length>]) an array type
|
|
||||||
* length must be specified for return and result parameters
|
|
||||||
* if specified, length can be any of
|
|
||||||
** an integer, for a fixed size
|
|
||||||
** the symbol null, indicating a NULL-terminated array
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
0.3
|
0.4
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
;; Note: this evolved as a throw-away script to provide certain core
|
;; Note: this evolved as a throw-away script to provide certain core
|
||||||
;; modules, and so is a mess. Tread carefully.
|
;; modules, and so is a mess. Tread carefully.
|
||||||
|
|
||||||
;; Simple C FFI. "genstubs.scm file.stub" will read in the C function
|
;; Simple C FFI. "chibi-ffi file.stub" will read in the C function
|
||||||
;; FFI definitions from file.stub and output the appropriate C
|
;; FFI definitions from file.stub and output the appropriate C
|
||||||
;; wrappers into file.c. You can then compile that file with:
|
;; wrappers into file.c. You can then compile that file with:
|
||||||
;;
|
;;
|
||||||
|
@ -13,6 +13,9 @@
|
||||||
;; your platform) and then the generated .so file can be loaded
|
;; your platform) and then the generated .so file can be loaded
|
||||||
;; directly with load, or portably using (include-shared "file") in a
|
;; directly with load, or portably using (include-shared "file") in a
|
||||||
;; module definition (note that include-shared uses no suffix).
|
;; module definition (note that include-shared uses no suffix).
|
||||||
|
;;
|
||||||
|
;; Passing the -c/--compile option will attempt to compile the .so
|
||||||
|
;; file in a single step.
|
||||||
|
|
||||||
;; The goal of this interface is to make access to C types and
|
;; The goal of this interface is to make access to C types and
|
||||||
;; functions easy, without requiring the user to write any C code.
|
;; functions easy, without requiring the user to write any C code.
|
||||||
|
@ -22,119 +25,6 @@
|
||||||
;; several of the core modules provide C interfaces directly without
|
;; several of the core modules provide C interfaces directly without
|
||||||
;; using the stubber.
|
;; using the stubber.
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;; Struct Interface
|
|
||||||
;;
|
|
||||||
;; (define-c-struct struct-name
|
|
||||||
;; [predicate: predicate-name]
|
|
||||||
;; [constructor: constructor-name]
|
|
||||||
;; [finalizer: c_finalizer_name]
|
|
||||||
;; (type c_field_name getter-name setter-name) ...)
|
|
||||||
;;
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;; Function Interface
|
|
||||||
;;
|
|
||||||
;; (define-c return-type name-spec (arg-type ...))
|
|
||||||
;;
|
|
||||||
;; where name-space is either a symbol name, or a list of
|
|
||||||
;; (scheme-name c_name). If just a symbol, the C name is taken
|
|
||||||
;; to be the same with -'s replaced by _'s.
|
|
||||||
;;
|
|
||||||
;; arg-type is a type suitable for input validation and conversion.
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;; Types
|
|
||||||
;;
|
|
||||||
;; Types
|
|
||||||
;;
|
|
||||||
;; Basic Types
|
|
||||||
;; void
|
|
||||||
;; boolean
|
|
||||||
;; char
|
|
||||||
;; sexp (no conversions)
|
|
||||||
;;
|
|
||||||
;; Integer Types:
|
|
||||||
;; signed-char short int long
|
|
||||||
;; unsigned-char unsigned-short unsigned-int unsigned-long size_t pid_t
|
|
||||||
;; time_t (in seconds, but using the chibi epoch of 2010/01/01)
|
|
||||||
;; errno (as a return type returns #f on error)
|
|
||||||
;;
|
|
||||||
;; Float Types:
|
|
||||||
;; float double long-double
|
|
||||||
;;
|
|
||||||
;; String Types:
|
|
||||||
;; string - a null-terminated char*
|
|
||||||
;; env-string - a VAR=VALUE string represented as a (VAR . VALUE) pair inScheme
|
|
||||||
;; in addition you can use (array char) as a string
|
|
||||||
;;
|
|
||||||
;; Port Types:
|
|
||||||
;; input-port output-port
|
|
||||||
;; port-or-fd - an fd-backed port or a fixnum
|
|
||||||
;;
|
|
||||||
;; Struct Types:
|
|
||||||
;;
|
|
||||||
;; Struct types are by default just referred to by the bare
|
|
||||||
;; struct-name from define-c-struct, and it is assumed you want a
|
|
||||||
;; pointer to that type. To refer to the full struct, use the struct
|
|
||||||
;; modifier, as in (struct struct-name).
|
|
||||||
|
|
||||||
;; Type modifiers
|
|
||||||
;;
|
|
||||||
;; Any type may also be written as a list of modifiers followed by the
|
|
||||||
;; type itself. The supported modifiers are:
|
|
||||||
;;
|
|
||||||
;; const: prepends the "const" C type modifier
|
|
||||||
;; * as a return or result parameter, makes non-immediates immutable
|
|
||||||
;;
|
|
||||||
;; free: it's Scheme's responsibility to "free" this resource
|
|
||||||
;; * as a return or result parameter, registers the freep flag
|
|
||||||
;; this causes the type finalizer to be run when GCed
|
|
||||||
;;
|
|
||||||
;; maybe-null: this pointer type may be NULL
|
|
||||||
;; * as a result parameter, NULL is translated to #f
|
|
||||||
;; normally this would just return a wrapped NULL pointer
|
|
||||||
;; * as an input parameter, #f is translated to NULL
|
|
||||||
;; normally this would be a type error
|
|
||||||
;;
|
|
||||||
;; pointer: create a pointer to this type
|
|
||||||
;; * as a return parameter, wraps the result in a vanilla cpointer
|
|
||||||
;; * as a result parameter, boxes then unboxes the value
|
|
||||||
;;
|
|
||||||
;; struct: treat this struct type as a struct, not a pointer
|
|
||||||
;; * as an input parameter, dereferences the pointer
|
|
||||||
;; * as a type field, indicates a nested struct
|
|
||||||
;;
|
|
||||||
;; link: add a gc link
|
|
||||||
;; * as a field getter, link to the parent object, so the
|
|
||||||
;; parent won't be GCed so long as we have a reference
|
|
||||||
;; to the child. this behavior is automatic for nested
|
|
||||||
;; structs.
|
|
||||||
;;
|
|
||||||
;; result: return a result in this parameter
|
|
||||||
;; * if there are multiple results (including the return type),
|
|
||||||
;; they are all returned in a list
|
|
||||||
;; * if there are any result parameters, a return type
|
|
||||||
;; of errno returns #f on failure, and as eliminated
|
|
||||||
;; from the list of results otherwise
|
|
||||||
;;
|
|
||||||
;; (value <expr>): specify a fixed value
|
|
||||||
;; * as an input parameter, this parameter is not provided
|
|
||||||
;; in the Scheme API but always passed as <expr>
|
|
||||||
;;
|
|
||||||
;; (default <expr>): specify a default value
|
|
||||||
;; * as the final input parameter, makes the Scheme parameter
|
|
||||||
;; optional, defaulting to <expr>
|
|
||||||
;;
|
|
||||||
;; (array <type> [<length>]) an array type
|
|
||||||
;; * length must be specified for return and result parameters
|
|
||||||
;; * if specified, length can be any of
|
|
||||||
;; ** an integer, for a fixed size
|
|
||||||
;; ** the symbol null, indicating a NULL-terminated array
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; globals
|
;; globals
|
||||||
|
|
||||||
|
@ -336,10 +226,20 @@
|
||||||
((eqv? c (string-ref str i)) (lp (+ i 1) (+ i 1) (cons r (collect))))
|
((eqv? c (string-ref str i)) (lp (+ i 1) (+ i 1) (cons r (collect))))
|
||||||
(else (lp from (+ i 1) res))))))
|
(else (lp from (+ i 1) res))))))
|
||||||
|
|
||||||
|
(define (string-split str c . o)
|
||||||
|
(let ((start (if (pair? o) (car o) 0))
|
||||||
|
(end (string-length str)))
|
||||||
|
(let lp ((from start) (i start) (res '()))
|
||||||
|
(define (collect) (if (= i from) res (cons (substring str from i) res)))
|
||||||
|
(cond
|
||||||
|
((>= i end) (reverse (collect)))
|
||||||
|
((eqv? c (string-ref str i)) (lp (+ i 1) (+ i 1) (collect)))
|
||||||
|
(else (lp from (+ i 1) res))))))
|
||||||
|
|
||||||
(define (string-scan c str . o)
|
(define (string-scan c str . o)
|
||||||
(let ((limit (string-length str)))
|
(let ((end (string-length str)))
|
||||||
(let lp ((i (if (pair? o) (car o) 0)))
|
(let lp ((i (if (pair? o) (car o) 0)))
|
||||||
(cond ((>= i limit) #f)
|
(cond ((>= i end) #f)
|
||||||
((eqv? c (string-ref str i)) i)
|
((eqv? c (string-ref str i)) i)
|
||||||
(else (lp (+ i 1)))))))
|
(else (lp (+ i 1)))))))
|
||||||
|
|
||||||
|
@ -1288,13 +1188,31 @@
|
||||||
;; main
|
;; main
|
||||||
|
|
||||||
(define (main args)
|
(define (main args)
|
||||||
(case (length args)
|
(let* ((compile? (and (pair? args) (member (car args) '("-c" "--compile"))))
|
||||||
((1)
|
(args (if compile? (cdr args) args))
|
||||||
(with-output-to-file (string-append (strip-extension (car args)) ".c")
|
(cflags (if (and (pair? args) (member (car args) '("-f" "--flags")))
|
||||||
(lambda () (generate (car args)))))
|
(string-split (cadr args) " ")
|
||||||
((2)
|
#f))
|
||||||
(if (equal? "-" (cadr args))
|
(args (if cflags (cddr args) args))
|
||||||
(generate (car args))
|
(src (car args))
|
||||||
(with-output-to-file (cadr args) (lambda () (generate (car args))))))
|
(dest
|
||||||
(else
|
(case (length args)
|
||||||
(error "usage: genstubs <file.stub> [<output.c>]"))))
|
((1) (string-append (strip-extension src) ".c"))
|
||||||
|
((2) (cadr args))
|
||||||
|
(else (error "usage: chibi-ffi [-c] <file.stub> [<output.c>]")))))
|
||||||
|
(if (equal? "-" dest)
|
||||||
|
(generate src)
|
||||||
|
(with-output-to-file dest (lambda () (generate src))))
|
||||||
|
(cond
|
||||||
|
((and compile? (not (equal? "-" dest)))
|
||||||
|
;; This has to use `eval' for bootstrapping, since we need
|
||||||
|
;; chibi-ffi to compile to (chibi process) module.
|
||||||
|
(let* ((so (string-append (strip-extension src) *shared-object-extension*))
|
||||||
|
(system (begin (eval '(import (chibi process)))
|
||||||
|
(eval 'system)))
|
||||||
|
(base-args (append (or cflags '())
|
||||||
|
`("-o" ,so ,dest "-lchibi-scheme")))
|
||||||
|
(args (cond-expand
|
||||||
|
(macosx (append '("-dynamiclib" "-Oz") base-args))
|
||||||
|
(else (append '("-fPIC" "-shared" "-Os") base-args)))))
|
||||||
|
(apply system "cc" args))))))
|
Loading…
Add table
Reference in a new issue