summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-12-06 06:17:45 -0800
committerKaz Kylheku <kaz@kylheku.com>2019-12-06 06:17:45 -0800
commitf018af6fe6b0c867c747217890b8b02d8e6d7ffb (patch)
tree9b52ade1de02c1420f3858fa1c32d70b6bbc0eaa /ffi.c
parent45412f6aef55df4f83f54b2b5445f673bfeee691 (diff)
downloadtxr-f018af6fe6b0c867c747217890b8b02d8e6d7ffb.tar.gz
txr-f018af6fe6b0c867c747217890b8b02d8e6d7ffb.tar.bz2
txr-f018af6fe6b0c867c747217890b8b02d8e6d7ffb.zip
ffi: allow init-forms for slots.
* ffi.c (ffi_memb_compile): Don't complain about three-argument slot specifiers, only about longer ones. (ffi_struct_init): New static function. (ffi_type_compile): Deal with third element in the slot syntax. If there are any non-nil initializing expressions, then we when we call make_struct_type, we specify an initfun, which will plant the values into the slots, using logic similar to that of the initfun generated defstruct, except that the init-forms are reduced to values up-front. * txr.1: Specify optional init-form for slots in FFI struct syntax.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/ffi.c b/ffi.c
index fe7cf5d6..7be1d187 100644
--- a/ffi.c
+++ b/ffi.c
@@ -2811,7 +2811,7 @@ static val ffi_memb_compile(val syntax, int last, int *pflexp, val self)
val type = cadr(syntax);
val comp_type = ffi_type_compile(type);
struct txr_ffi_type *ctft = ffi_type_struct(comp_type);
- if (cddr(syntax))
+ if (consp(cddr(syntax)) && cdddr(syntax))
uw_throwf(error_s, lit("~a: excess elements in type-member pair ~s"),
self, syntax, nao);
if (ctft->flexible || (ctft->incomplete && ctft->kind == FFI_KIND_ARRAY)) {
@@ -3287,6 +3287,18 @@ static val ffi_type_lookup(val sym)
return gethash(ffi_typedef_hash, sym);
}
+static val ffi_struct_init(val slot_init, val strct)
+{
+ val stype = struct_type(strct);
+ for (; slot_init; slot_init = us_cdr(slot_init)) {
+ us_cons_bind(slot, initval, us_car(slot_init));
+ if (!static_slot_p(stype, slot))
+ slotset(strct, slot, initval);
+ }
+
+ return nil;
+}
+
val ffi_type_compile(val syntax)
{
val self = lit("ffi-type-compile");
@@ -3312,14 +3324,33 @@ val ffi_type_compile(val syntax)
}
} else {
uses_or2;
- val slots = mapcar(car_f, membs);
- val stype = or2(if2(name, find_struct_type(sname)),
- make_struct_type(sname, nil, nil,
- remq(nil, slots, nil),
- nil, nil, nil, nil));
- val xsyntax = cons(struct_s,
- cons(sname, membs));
- return make_ffi_type_struct(xsyntax, stype, existing_type, self);
+ val iter;
+ list_collect_decl (slots, ptslots);
+ list_collect_decl (slot_inits, ptinits);
+
+ for (iter = membs; iter; iter = cdr(iter)) {
+ val spec = car(iter);
+ val slot = car(spec);
+ val init = caddr(spec);
+ if (!slot && init)
+ uw_warningf(lit("~a: padding slot struct ~s specifies init-form"),
+ self, name, nao);
+ if (slot)
+ ptslots = list_collect(ptslots, slot);
+ if (slot && init)
+ ptinits = list_collect(ptinits, cons(slot, ffi_eval_expr(init, nil, nil)));
+ }
+
+ {
+ val stype = or2(if2(name, find_struct_type(sname)),
+ make_struct_type(sname, nil, nil,
+ slots, nil,
+ if2(slot_inits, func_f1(slot_inits, ffi_struct_init)),
+ nil, nil));
+ val xsyntax = cons(struct_s,
+ cons(sname, membs));
+ return make_ffi_type_struct(xsyntax, stype, existing_type, self);
+ }
}
} else if (sym == union_s) {
val name = cadr(syntax);