summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-20 22:40:53 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-20 22:40:53 -0700
commit8f9697ed8f42681ab0df16ab38859d61ea05412e (patch)
tree10a7a50b5e7a0d26d11ddb5e3cf238f874e187ac /ffi.c
parent378318ef010dfb15045dfadf242231793d1434de (diff)
downloadtxr-8f9697ed8f42681ab0df16ab38859d61ea05412e.tar.gz
txr-8f9697ed8f42681ab0df16ab38859d61ea05412e.tar.bz2
txr-8f9697ed8f42681ab0df16ab38859d61ea05412e.zip
ffi: testing and fixing flexible arrays.
* ffi.c (ffi_flex_struct_in): Check for the last member being an array, and not null-terminated. We now check the character conversion disposition of the array. If it has character conversion, then we store the length right into the slot that will become the string. In the no-conversion case, we assume that if the member exists, it's a vector we can resize. Otherwise we plant a vector of the required size. (ffi_varray_put): Only call ffi_varray_dynsize if the Lisp object is a vector. If the Lisp objecct is a number, then use that as the size. Otherwise the size is zero. * tests/017/flexstruct.tl: New file.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/ffi.c b/ffi.c
index 13e8769b..18382cf6 100644
--- a/ffi.c
+++ b/ffi.c
@@ -2446,17 +2446,33 @@ static void ffi_ptr_in_release(struct txr_ffi_type *tft, val obj,
static val ffi_flex_struct_in(struct txr_ffi_type *tft, val strct, val self)
{
struct smemb *lastm = &tft->memb[tft->nelem - 1];
- val length_meth = get_special_slot(strct, length_m);
-
+ struct txr_ffi_type *lmtft = lastm->mtft;
(void) self;
- if (length_meth) {
- val len = funcall1(length_meth, strct);
- val memb = slot(strct, lastm->mname);
- if (vectorp(memb))
- return vec_set_length(memb, len);
- else
- return slotset(strct, lastm->mname, vector(len, nil));
+ if (lmtft->kind == FFI_KIND_ARRAY && !lmtft->null_term) {
+ val length_meth = get_special_slot(strct, length_m);
+
+ if (length_meth) {
+ val len = funcall1(length_meth, strct);
+
+ switch (lmtft->ch_conv) {
+ case conv_char:
+ case conv_zchar:
+ case conv_wchar:
+ case conv_bchar:
+ slotset(strct, lastm->mname, len);
+ break;
+ case conv_none:
+ {
+ val memb = slot(strct, lastm->mname);
+ if (memb)
+ return vec_set_length(memb, len);
+ else
+ return slotset(strct, lastm->mname, vector(len, nil));
+ }
+ break;
+ }
+ }
}
return slot(strct, lastm->mname);
@@ -2978,7 +2994,14 @@ static val ffi_varray_in(struct txr_ffi_type *tft, int copy, mem_t *src,
{
if (copy) {
struct txr_ffi_type *etft = ffi_type_struct(tft->eltype);
- cnum nelem = if3(vec, ffi_varray_dynsize(tft, vec, self) / etft->size, 0);
+ cnum nelem = 0;
+
+ if (vectorp(vec)) {
+ nelem = ffi_varray_dynsize(tft, vec, self) / etft->size;
+ } else if (numberp(vec)) {
+ nelem = c_num(vec, self);
+ vec = nil;
+ }
switch (tft->ch_conv) {
case conv_char: