From 310a04f701eb249ba26fc3d069c62d3e46443b5d Mon Sep 17 00:00:00 2001 From: Dimitris Papavasiliou Date: Tue, 4 Oct 2022 21:33:34 +0300 Subject: [PATCH] Add support for user exported C libraries This uses the existing mechanism for statically compiled C libraries, to allow the user to export their own C libraries in a similar way. User exported libraries can be added on top of statically compiled C libraries or exist on their own (by setting SEXP_USE_STATIC_LIBS_EMPTY). --- eval.c | 39 ++++++++++++++++++++++++++++++++++----- include/chibi/features.h | 35 +++++++++++++++++++++++++---------- include/chibi/sexp.h | 14 ++++++++++++-- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/eval.c b/eval.c index 9d1d09f2..14224ee9 100644 --- a/eval.c +++ b/eval.c @@ -1374,24 +1374,53 @@ sexp sexp_stream_portp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port) { #endif #if SEXP_USE_STATIC_LIBS -#if SEXP_USE_STATIC_LIBS_NO_INCLUDE +#if SEXP_USE_STATIC_LIBS_EMPTY +struct sexp_library_entry_t* sexp_static_libraries = NULL; +#elif SEXP_USE_STATIC_LIBS_NO_INCLUDE extern struct sexp_library_entry_t* sexp_static_libraries; #else #include "clibs.c" #endif + +void sexp_add_static_libraries(struct sexp_library_entry_t* libraries) +{ + struct sexp_library_entry_t *entry, *table; + + if (!sexp_static_libraries) { + sexp_static_libraries = libraries; + return; + } + + for (table = sexp_static_libraries; ; + table = (struct sexp_library_entry_t*)entry->init) { + for (entry = &table[0]; entry->name; entry++) + ; + if (!entry->init) { + entry->init = (sexp_init_proc)libraries; + return; + } + } +} + static struct sexp_library_entry_t *sexp_find_static_library(const char *file) { size_t base_len; - struct sexp_library_entry_t *entry; + struct sexp_library_entry_t *entry, *table; + if(!sexp_static_libraries) + return NULL; if (file[0] == '.' && file[1] == '/') file += 2; base_len = strlen(file) - strlen(sexp_so_extension); if (strcmp(file + base_len, sexp_so_extension)) return NULL; - for (entry = &sexp_static_libraries[0]; entry->name; entry++) - if (! strncmp(file, entry->name, base_len)) - return entry; + for (table = sexp_static_libraries; + table; + table = (struct sexp_library_entry_t*)entry->init) { + for (entry = &table[0]; entry->name; entry++) + if (! strncmp(file, entry->name, base_len)) + return entry; + } return NULL; } #else diff --git a/include/chibi/features.h b/include/chibi/features.h index ff977de7..dd8deb21 100644 --- a/include/chibi/features.h +++ b/include/chibi/features.h @@ -23,16 +23,27 @@ /* sexp_init_library(ctx, env) function provided. */ /* #define SEXP_USE_DL 0 */ -/* uncomment this to statically compile all C libs */ -/* If set, this will statically include the clibs.c file */ -/* into the standard environment, so that you can have */ -/* access to a predefined set of C libraries without */ -/* needing dynamic loading. The clibs.c file is generated */ -/* automatically by searching the lib directory for */ -/* modules with include-shared, but can be hand-tailored */ -/* to your needs. */ +/* uncomment this to support statically compiled C libs */ +/* Unless SEXP_USE_STATIC_LIBS_EMPTY is set (see below), this */ +/* will statically include the clibs.c file into the standard */ +/* environment, so that you can have access to a predefined set */ +/* of C libraries without needing dynamic loading. The clibs.c */ +/* file is generated automatically by searching the lib directory */ +/* for modules with include-shared, but can be hand-tailored to */ +/* your needs. You can also register your own C libraries using */ +/* sexp_add_static_libraries (see below). */ /* #define SEXP_USE_STATIC_LIBS 1 */ +/* uncomment this to enable user exported C libs */ +/* You can register your own C libraries using */ +/* sexp_add_static_libraries. Each entry in the supplied table, */ +/* is a name/entry point pair. These work as if they were */ +/* dynamically loaded libraries, so naming follows the same */ +/* conventions. An entry {"foo", init_foo} will register a */ +/* library that can be loaded with (load "foo"), or */ +/* (include-shared "foo"), both of which will call init_foo. */ +/* #define SEXP_USE_STATIC_LIBS_EMPTY 1 */ + /* uncomment this to disable detailed source info for debugging */ /* By default Chibi will associate source info with every */ /* bytecode offset. By disabling this only lambda-level source */ @@ -461,13 +472,17 @@ #endif #endif +#ifndef SEXP_USE_STATIC_LIBS_EMPTY +#define SEXP_USE_STATIC_LIBS_EMPTY 0 +#endif + #ifndef SEXP_USE_STATIC_LIBS -#define SEXP_USE_STATIC_LIBS 0 +#define SEXP_USE_STATIC_LIBS SEXP_USE_STATIC_LIBS_EMPTY #endif /* don't include clibs.c - include separately or link */ #ifndef SEXP_USE_STATIC_LIBS_NO_INCLUDE -#ifdef PLAN9 +#if defined(PLAN9) || SEXP_USE_STATIC_LIBS_EMPTY #define SEXP_USE_STATIC_LIBS_NO_INCLUDE 0 #else #define SEXP_USE_STATIC_LIBS_NO_INCLUDE 1 diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 3ff3b53b..5ae0eb35 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -395,8 +395,8 @@ struct sexp_gc_var_t { struct sexp_gc_var_t *next; }; -struct sexp_library_entry_t { /* for static builds */ - const char *name; +struct sexp_library_entry_t { /* for static builds and user exported C */ + const char *name; /* libaries */ sexp_init_proc init; }; @@ -1680,6 +1680,16 @@ sexp sexp_finalize_dl (sexp ctx, sexp self, sexp_sint_t n, sexp dl); #define sexp_current_source_param #endif +/* To export a library from the embedding C program to Scheme, so */ +/* that it can be included into Scheme library foo/qux.sld as */ +/* (include-shared "bar"), libraries should contain the entry */ +/* {"foo/bar", init_bar}. The signature and function of init_bar is */ +/* the same as that of sexp_init_library in shared libraries. The */ +/* array libraries must be terminated with {NULL, NULL} and must */ +/* remain valid throughout its use by Chibi. */ + +SEXP_API void sexp_add_static_libraries(struct sexp_library_entry_t* libraries); + SEXP_API sexp sexp_alloc_tagged_aux(sexp ctx, size_t size, sexp_uint_t tag sexp_current_source_param); SEXP_API sexp sexp_make_context(sexp ctx, size_t size, size_t max_size); SEXP_API sexp sexp_cons_op(sexp ctx, sexp self, sexp_sint_t n, sexp head, sexp tail);