summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-06-10 16:04:48 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-06-10 16:04:48 -0700
commit430e4c7082f89b75ca9fc5af11674392aaefdffb (patch)
tree5e6f6b57bb722362008e461de306ba0d1e85cadf
parent8720c828d956fd29d9266d0e06cb7ead69d5ab95 (diff)
downloadtxr-430e4c7082f89b75ca9fc5af11674392aaefdffb.tar.gz
txr-430e4c7082f89b75ca9fc5af11674392aaefdffb.tar.bz2
txr-430e4c7082f89b75ca9fc5af11674392aaefdffb.zip
ffi: retain some functionality if libffi missing.
The FFI module is more than just foreign calls and callbacks; it provides a type system and operations for working with binary data. None of it depends on libffi being present and so shouldn't be disabled if libffi is not available. * Makefile (ffi.o): Unconditionally link this object file, not subject to the have_libffi variable. * configure (have_libffi): Variable removed. (gen_config_make): Do not generate a have_libffi variable into config.make, since nothing needs it. * ffi.c (ffi_type): Fake ffi_type defined if libffi is missing. (FFI_TYPE_STRUCT): Fake macro. (ffi_type ffi_type_void, ffi_type_pointer, ffi_type_sint, ffi_type ffi_type_schar, ffi_type_uchar, ffi_type ffi_type_sshort, ffi_type_ushort, ffi_type ffi_type_sint, ffi_type_uint, ffi_type ffi_type_slong, ffi_type_ulong, ffi_type ffi_type_sint8, ffi_type_uint8, ffi_type ffi_type_sint16, ffi_type_uint16, ffi_type ffi_type_sint32, ffi_type_uint32, ffi_type ffi_type_sint64, ffi_type_uint64, ffi_type ffi_type_float, ffi_type_double): Fake libffi type objects, so that code which references these things will build without modification. (ffi_get_type): Function only defined if we have libffi. (ffi_type_struct_destroy_op, ffi_struct_clone, make_ffi_type_struct, ffi_array_clone, make_ffi_type_array): Don't work with ffi_type's element array if we don't have libffi; our fake ffi_type doesn't have such an array. (struct txr_ffi_closure): Type only defined if we have libffi. (ffi_closure_struct, ffi_closure_struct_checked, ffi_closure_print_op, ffi_closure_destroy_op, ffi_closure_mark_op, ffi_closure_put): Functions only defined if we have libffi. (ffi_closure_ops): Static structure only defined if we have libffi. (ffi_init_types): Don't register a closure type if we don't have libffi. (struct txr_ffi_call_desc): Don't define type if we don't have libffi. (ffi_call_desc, ffi_call_desc_checked, ffi_call_desc_print_op, ffi_call_desc_destroy_op, ffi_call_desc_mark_op, ffi_make_call_desc, ffi_call_wrap, ffi_closure_dispatch, ffi_closure_dispatch_safe, ffi_make_closure, ffi_closure_get_fptr): Functions only defined if we have libffi. (ffi_call_desc_ops): Static structure only defined if we have libffi. (ffi_init): Only register ffi-make-call-desc, ffi-call, and ffi-make-closure if we have libffi. * lib.c: Include "ffi.h" header unconditionally. (generic_funcall, ref, refset, int): Remove #if HAVE_LIBFFI.
-rw-r--r--Makefile3
-rwxr-xr-xconfigure5
-rw-r--r--ffi.c72
-rw-r--r--lib.c10
4 files changed, 71 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index 531395cd..ae3c7fd3 100644
--- a/Makefile
+++ b/Makefile
@@ -49,7 +49,7 @@ EXTRA_OBJS-y :=
OBJS := txr.o lex.yy.o y.tab.o match.o lib.o regex.o gc.o unwind.o stream.o
OBJS += arith.o hash.o utf8.o filter.o eval.o parser.o rand.o combi.o sysif.o
-OBJS += args.o lisplib.o cadr.o struct.o itypes.o buf.o jmp.o protsym.o
+OBJS += args.o lisplib.o cadr.o struct.o itypes.o buf.o jmp.o protsym.o ffi.o
OBJS-$(debug_support) += debug.o
OBJS-$(have_syslog) += syslog.o
OBJS-$(have_glob) += glob.o
@@ -58,7 +58,6 @@ OBJS-$(have_posix_sigs) += signal.o
OBJS-$(have_sockets) += socket.o
OBJS-$(have_termios) += termios.o
OBJS-$(have_termios) += linenoise/linenoise.o
-OBJS-$(have_libffi) += ffi.o
EXTRA_OBJS-$(add_win_res) += win/txr.res
ifneq ($(have_git),)
diff --git a/configure b/configure
index 91228283..bf9d07fc 100755
--- a/configure
+++ b/configure
@@ -143,7 +143,6 @@ have_alloca=
have_termios=
have_winsize=
termios_define=
-have_libffi=
#
# Parse configuration variables
@@ -679,8 +678,6 @@ have_sockets := $have_sockets
have_termios := $have_termios
termios_define := $termios_define
-have_libffi := $have_libffi
-
# do we compile in debug support?
debug_support := $debug_support
@@ -2852,11 +2849,9 @@ int main(void)
if conftest ; then
printf "yes\n"
printf "#define HAVE_LIBFFI 1\n" >> config.h
- have_libffi=y
elif conftest EXTRA_LDFLAGS=-lffi ; then
printf "yes\n"
printf "#define HAVE_LIBFFI 1\n" >> config.h
- have_libffi=y
conf_ldflags="${conf_ldflags:+"$conf_ldflags "}-lffi"
else
printf "no\n"
diff --git a/ffi.c b/ffi.c
index f0974ddf..aa4813df 100644
--- a/ffi.c
+++ b/ffi.c
@@ -36,8 +36,10 @@
#include <wchar.h>
#include <dirent.h>
#include <time.h>
-#include <ffi.h>
#include "config.h"
+#if HAVE_LIBFFI
+#include <ffi.h>
+#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -74,6 +76,12 @@
#define ifbe2(expr1, expr2) (expr1)
#endif
+#if !HAVE_LIBFFI
+typedef struct ffi_type {
+ char type, size;
+} ffi_type;
+#define FFI_TYPE_STRUCT 0
+#endif
val uint8_s, int8_s;
val uint16_s, int16_s;
@@ -122,7 +130,22 @@ val ffi_type_s, ffi_call_desc_s, ffi_closure_s;
static val ffi_typedef_hash;
+#if HAVE_LIBFFI
static uw_frame_t *s_exit_point;
+#endif
+
+#if !HAVE_LIBFFI
+static ffi_type ffi_type_void, ffi_type_pointer, ffi_type_sint;
+static ffi_type ffi_type_schar, ffi_type_uchar;
+static ffi_type ffi_type_sshort, ffi_type_ushort;
+static ffi_type ffi_type_sint, ffi_type_uint;
+static ffi_type ffi_type_slong, ffi_type_ulong;
+static ffi_type ffi_type_sint8, ffi_type_uint8;
+static ffi_type ffi_type_sint16, ffi_type_uint16;
+static ffi_type ffi_type_sint32, ffi_type_uint32;
+static ffi_type ffi_type_sint64, ffi_type_uint64;
+static ffi_type ffi_type_float, ffi_type_double;
+#endif
struct smemb {
val mname;
@@ -169,11 +192,13 @@ static struct txr_ffi_type *ffi_type_struct_checked(val obj)
return coerce(struct txr_ffi_type *, cobj_handle(obj, ffi_type_s));
}
+#if HAVE_LIBFFI
static ffi_type *ffi_get_type(val obj)
{
struct txr_ffi_type *tffi = ffi_type_struct_checked(obj);
return tffi->ft;
}
+#endif
static val ffi_get_lisp_type(val obj)
{
@@ -192,11 +217,17 @@ static void ffi_type_print_op(val obj, val out, val pretty, struct strm_ctx *ctx
static void ffi_type_struct_destroy_op(val obj)
{
struct txr_ffi_type *tft = ffi_type_struct(obj);
+#if HAVE_LIBFFI
ffi_type *ft = tft->ft;
+#endif
+
+#if HAVE_LIBFFI
free(ft->elements);
ft->elements = 0;
free(ft);
tft->ft = 0;
+#endif
+
free(tft->memb);
tft->memb = 0;
free(tft);
@@ -274,6 +305,8 @@ static struct cobj_ops ffi_type_enum_ops =
ffi_enum_type_mark,
cobj_eq_hash_op);
+#if HAVE_LIBFFI
+
struct txr_ffi_closure {
ffi_closure *clo;
mem_t *fptr;
@@ -329,6 +362,8 @@ static struct cobj_ops ffi_closure_ops =
ffi_closure_mark_op,
cobj_eq_hash_op);
+#endif
+
static void ffi_void_put(struct txr_ffi_type *tft, val n, mem_t *dst, val self)
{
}
@@ -1885,6 +1920,7 @@ static val ffi_buf_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
return ret;
}
+#if HAVE_LIBFFI
static void ffi_closure_put(struct txr_ffi_type *tft, val ptr, mem_t *dst,
val self)
{
@@ -1903,6 +1939,7 @@ static void ffi_closure_put(struct txr_ffi_type *tft, val ptr, mem_t *dst,
memcpy(dst, &p, sizeof p);
}
+#endif
static val ffi_ptr_in_in(struct txr_ffi_type *tft, int copy, mem_t *src,
val obj, val self)
@@ -2667,15 +2704,19 @@ static struct txr_ffi_type *ffi_struct_clone(struct txr_ffi_type *orig)
{
cnum nmemb = orig->nelem;
struct txr_ffi_type *copy = ffi_simple_clone(orig);
+#if HAVE_LIBFFI
size_t elements_size = sizeof *orig->ft->elements * (nmemb + 1);
+#endif
size_t memb_size = sizeof *orig->memb * nmemb;
ffi_type *ft = coerce(ffi_type *, chk_copy_obj(coerce(mem_t *, orig->ft),
sizeof *orig->ft));
copy->ft = ft;
+#if HAVE_LIBFFI
ft->elements = coerce(ffi_type **, chk_copy_obj(coerce(mem_t *,
ft->elements),
elements_size));
+#endif
copy->memb = coerce(struct smemb *, chk_copy_obj(coerce(mem_t *,
orig->memb),
memb_size));
@@ -2691,8 +2732,10 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
ffi_type *ft = coerce(ffi_type *, chk_calloc(1, sizeof *ft));
cnum nmemb = c_num(length(types)), i;
+#if HAVE_LIBFFI
ffi_type **elements = coerce(ffi_type **,
chk_malloc(sizeof *elements * (nmemb + 1)));
+#endif
struct smemb *memb = coerce(struct smemb *,
chk_calloc(nmemb, sizeof *memb));
val obj = cobj(coerce(mem_t *, tft), ffi_type_s, &ffi_type_struct_ops);
@@ -2724,7 +2767,9 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
struct txr_ffi_type *mtft = ffi_type_struct(type);
cnum size = mtft->size;
+#if HAVE_LIBFFI
elements[i] = mtft->ft;
+#endif
memb[i].mtype = type;
memb[i].mname = slot;
@@ -2800,12 +2845,16 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
tft->nelem = i;
+#if HAVE_LIBFFI
elements[i] = 0;
+#endif
if (need_out_handler)
tft->out = ffi_struct_out;
+#if HAVE_LIBFFI
ft->elements = elements;
+#endif
tft->size = (offs + most_align - 1) & ~(most_align - 1);
tft->align = most_align;
@@ -2815,16 +2864,20 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
static struct txr_ffi_type *ffi_array_clone(struct txr_ffi_type *orig)
{
- cnum nmemb = orig->nelem;
struct txr_ffi_type *copy = ffi_simple_clone(orig);
+#if HAVE_LIBFFI
+ cnum nmemb = orig->nelem;
size_t elements_size = sizeof *orig->ft->elements * (nmemb + 1);
+#endif
ffi_type *ft = coerce(ffi_type *, chk_copy_obj(coerce(mem_t *, orig->ft),
sizeof *orig->ft));
copy->ft = ft;
+#if HAVE_LIBFFI
ft->elements = coerce(ffi_type **, chk_copy_obj(coerce(mem_t *,
ft->elements),
elements_size));
+#endif
return copy;
}
@@ -2836,8 +2889,10 @@ static val make_ffi_type_array(val syntax, val lisp_type,
ffi_type *ft = coerce(ffi_type *, chk_calloc(1, sizeof *ft));
cnum nelem = c_num(dim), i;
+#if HAVE_LIBFFI
ffi_type **elements = coerce(ffi_type **, chk_malloc(sizeof *elements *
(nelem + 1)));
+#endif
val obj = cobj(coerce(mem_t *, tft), ffi_type_s, &ffi_type_struct_ops);
struct txr_ffi_type *etft = ffi_type_struct(eltype);
@@ -2858,7 +2913,9 @@ static val make_ffi_type_array(val syntax, val lisp_type,
tft->free = free;
for (i = 0; i < nelem; i++) {
+#if HAVE_LIBFFI
elements[i] = etft->ft;
+#endif
if (i == 0) {
tft->size = etft->size * nelem;
tft->align = etft->align;
@@ -2867,9 +2924,11 @@ static val make_ffi_type_array(val syntax, val lisp_type,
}
}
+#if HAVE_LIBFFI
elements[i] = 0;
ft->elements = elements;
+#endif
tft->nelem = nelem;
@@ -3579,12 +3638,15 @@ static void ffi_init_types(void)
}
}
+#if HAVE_LIBFFI
ffi_typedef(closure_s, make_ffi_type_builtin(closure_s, fun_s,
sizeof (mem_t *),
alignof (mem_t *),
&ffi_type_pointer,
ffi_closure_put, ffi_cptr_get,
0, 0));
+#endif
+
ffi_typedef(void_s, make_ffi_type_builtin(void_s, null_s, 0, 0,
&ffi_type_void,
ffi_void_put, ffi_void_get,
@@ -3687,6 +3749,8 @@ static void ffi_init_extra_types(void)
#endif
}
+#if HAVE_LIBFFI
+
struct txr_ffi_call_desc {
ffi_cif cif;
ffi_type **args;
@@ -4020,6 +4084,8 @@ mem_t *ffi_closure_get_fptr(val closure)
return tfcl->fptr;
}
+#endif
+
val ffi_typedef(val name, val type)
{
val self = lit("ffi-typedef");
@@ -4539,9 +4605,11 @@ void ffi_init(void)
ffi_call_desc_s = intern(lit("ffi-call-desc"), user_package);
ffi_closure_s = intern(lit("ffi-closure"), user_package);
reg_fun(intern(lit("ffi-type-compile"), user_package), func_n1(ffi_type_compile));
+#if HAVE_LIBFFI
reg_fun(intern(lit("ffi-make-call-desc"), user_package), func_n4(ffi_make_call_desc));
reg_fun(intern(lit("ffi-call"), user_package), func_n2v(ffi_call_wrap));
reg_fun(intern(lit("ffi-make-closure"), user_package), func_n4o(ffi_make_closure, 2));
+#endif
reg_fun(intern(lit("ffi-typedef"), user_package), func_n2(ffi_typedef));
reg_fun(intern(lit("ffi-size"), user_package), func_n1(ffi_size));
reg_fun(intern(lit("ffi-alignof"), user_package), func_n1(ffi_alignof));
diff --git a/lib.c b/lib.c
index 525a7824..4cb28c73 100644
--- a/lib.c
+++ b/lib.c
@@ -69,9 +69,7 @@
#include "struct.h"
#include "itypes.h"
#include "buf.h"
-#if HAVE_LIBFFI
#include "ffi.h"
-#endif
#include "txr.h"
#define max(a, b) ((a) > (b) ? (a) : (b))
@@ -5929,10 +5927,8 @@ val generic_funcall(val fun, struct args *args_in)
default:
callerror(fun, lit("too many arguments"));
}
-#if HAVE_LIBFFI
} else if (fun->co.cls == carray_s) {
goto carray;
-#endif
} else if (structp(fun)) {
fun = method(fun, lambda_s);
break;
@@ -9202,10 +9198,8 @@ val ref(val seq, val ind)
case COBJ:
if (seq->co.cls == hash_s)
return gethash(seq, ind);
-#if HAVE_LIBFFI
if (seq->co.cls == carray_s)
return carray_ref(seq, ind);
-#endif
/* fallthrough */
case CONS:
case LCONS:
@@ -9237,10 +9231,8 @@ val refset(val seq, val ind, val newval)
case COBJ:
if (seq->co.cls == hash_s)
return sethash(seq, ind, newval);
-#if HAVE_LIBFFI
if (seq->co.cls == carray_s)
return carray_refset(seq, ind, newval);
-#endif
default:
type_mismatch(lit("ref: ~s is not a sequence"), seq, nao);
}
@@ -11068,9 +11060,7 @@ void init(mem_t *(*oom)(mem_t *, size_t), val *stack_bottom)
struct_init();
itypes_init();
buf_init();
-#if HAVE_LIBFFI
ffi_init();
-#endif
sysif_init();
arith_init();
rand_init();