summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-04-24 06:47:10 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-04-24 06:47:10 -0700
commite93b91d8b2f239c8c85cb757487d488d4b91ca1b (patch)
tree73e1fbda2d18ead21c82ab794f84cdc3a58420f3 /ffi.c
parent7fbf6b853893f65193ea9c81cf467be08c651244 (diff)
downloadtxr-e93b91d8b2f239c8c85cb757487d488d4b91ca1b.tar.gz
txr-e93b91d8b2f239c8c85cb757487d488d4b91ca1b.tar.bz2
txr-e93b91d8b2f239c8c85cb757487d488d4b91ca1b.zip
carray: bug sweep.
The carray type is hereby reviewed for and repaired of issues related to the nelem member of struct carray using negative values to indicate "unknown carray size". * ffi.c (struct carray): The artype becomes a two-element array of values, so a carray can have a cache of separate null-terminated and non-null-terminated array type descriptors. This way, we get rid of the dirty trick of mutating one type. (carray_mark_op): Mark the two-element artype. (make_carray): Initialize two-element artype to nil. (carray_set_length): Cache invalidation: reset both elements of artype to nil, because the type includes length information, which may now be wrong. (copy_carray): Throw exception if asked to copy carray of unknown length. This would happen in carray_dup anyway, but at least the diagnostic refers to copy-carray. (buf_carray): Avoid calling make_duplicate_buf with negative bytes value when the carray has unknown length; diagnose. (carray_ref, carray_refset): Don't translate negative index values if the length is unknown. (carray_sub, carray_replace): If the operation requires use of the length, and it is unknown, throw an exception. (carray_ensure_artype): Take a null_term paramter that is 0 or 1, and use it as an array index into artype to set up the correct type, with the correct value of the null_term member that is henceforth not mutated. (carray_get_common, carray_put_common): Pass the null_term argument down to carray_ensure_artype. Remove the mutation of the null_term member of the type structure.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c90
1 files changed, 62 insertions, 28 deletions
diff --git a/ffi.c b/ffi.c
index ed04b3f1..11264bfb 100644
--- a/ffi.c
+++ b/ffi.c
@@ -5103,7 +5103,7 @@ struct carray {
cnum nelem;
val ref;
cnum offs;
- val artype;
+ val artype[2];
};
static struct carray *carray_struct(val carray)
@@ -5131,7 +5131,8 @@ static void carray_mark_op(val obj)
struct carray *scry = carray_struct(obj);
gc_mark(scry->eltype);
gc_mark(scry->ref);
- gc_mark(scry->artype);
+ gc_mark(scry->artype[0]);
+ gc_mark(scry->artype[1]);
}
static void carray_destroy_op(val obj)
@@ -5166,7 +5167,7 @@ val make_carray(val type, mem_t *data, cnum nelem, val ref, cnum offs)
scry->data = data;
scry->nelem = nelem;
scry->ref = nil;
- scry->artype = nil;
+ scry->artype[0] = scry->artype[1] = nil;
obj = cobj(coerce(mem_t *, scry), carray_s, &carray_borrowed_ops);
scry->eltype = type;
scry->ref = ref;
@@ -5196,6 +5197,7 @@ val carray_set_length(val carray, val nelem)
carray, nao);
scry->nelem = nel;
+ scry->artype[0] = scry->artype[1] = nil;
return nil;
}
@@ -5272,9 +5274,12 @@ val copy_carray(val carray)
{
val self = lit("copy-carray");
struct carray *scry = carray_struct_checked(self, carray);
- val copy = make_carray(scry->eltype, scry->data, scry->nelem, nil, 0);
- carray_dup(copy);
- return copy;
+ if (scry->nelem >= 0) {
+ val copy = make_carray(scry->eltype, scry->data, scry->nelem, nil, 0);
+ carray_dup(copy);
+ return copy;
+ }
+ uw_throwf(error_s, lit("~a: size of ~s carray unknown"), self, carray, nao);
}
mem_t *carray_ptr(val carray, val type, val self)
@@ -5388,8 +5393,11 @@ val buf_carray(val carray)
val self = lit("buf-carray");
struct carray *scry = carray_struct_checked(self, carray);
struct txr_ffi_type *etft = scry->eltft;
- cnum bytes = scry->nelem * etft->size;
- return make_duplicate_buf(num(bytes), scry->data);
+ if (scry->nelem >= 0) {
+ cnum bytes = scry->nelem * etft->size;
+ return make_duplicate_buf(num(bytes), scry->data);
+ }
+ uw_throwf(error_s, lit("~a: size of ~s carray unknown"), self, carray, nao);
}
val carray_cptr(val cptr, val type, val len)
@@ -5455,7 +5463,7 @@ val carray_ref(val carray, val idx)
struct carray *scry = carray_struct_checked(self, carray);
cnum ix = c_num(idx);
- if (ix < 0)
+ if (ix < 0 && scry->nelem >= 0)
ix += scry->nelem;
if (ix < 0 || (scry->nelem >= 0 && ix >= scry->nelem)) {
@@ -5476,7 +5484,7 @@ val carray_refset(val carray, val idx, val newval)
struct carray *scry = carray_struct_checked(self, carray);
cnum ix = c_num(idx);
- if (ix < 0)
+ if (ix < 0 && scry->nelem >= 0)
ix += scry->nelem;
if (ix < 0 || (scry->nelem >= 0 && ix >= scry->nelem)) {
@@ -5502,14 +5510,23 @@ val carray_sub(val carray, val from, val to)
if (null_or_missing_p(from))
from = zero;
- if (null_or_missing_p(to))
+ if (null_or_missing_p(to)) {
+ if (ln < 0)
+ goto nolen;
to = len;
+ }
- if (minusp(to))
+ if (minusp(to)) {
+ if (ln < 0)
+ goto nolen;
to = plus(to, len);
+ }
- if (minusp(from))
+ if (minusp(from)) {
+ if (ln < 0)
+ goto nolen;
from = plus(from, len);
+ }
{
cnum fn = c_num(from);
@@ -5533,6 +5550,8 @@ val carray_sub(val carray, val from, val to)
return make_carray(scry->eltype, scry->data + fn * elsize, tn - fn, carray, 0);
}
+nolen:
+ uw_throwf(error_s, lit("~a: operation requires size of ~s to be known"), self, carray, nao);
}
val carray_replace(val carray, val values, val from, val to)
@@ -5556,6 +5575,8 @@ val carray_replace(val carray, val values, val from, val to)
self, nao);
while (seq_get(&wh_iter, &wh) && seq_get(&item_iter, &item)) {
+ if (ln < 0)
+ goto nolen;
if (ge(wh, len))
break;
carray_refset(carray, wh, item);
@@ -5563,13 +5584,20 @@ val carray_replace(val carray, val values, val from, val to)
return carray;
} else if (minusp(from)) {
+ if (ln < 0)
+ goto nolen;
from = plus(from, len);
}
- if (null_or_missing_p(to))
+ if (null_or_missing_p(to)) {
+ if (ln < 0)
+ goto nolen;
to = len;
- else if (minusp(to))
+ } else if (minusp(to)) {
+ if (ln < 0)
+ goto nolen;
to = plus(to, len);
+ }
{
val vlen = length(values);
@@ -5632,26 +5660,34 @@ val carray_replace(val carray, val values, val from, val to)
return carray;
}
+nolen:
+ uw_throwf(error_s, lit("~a: operation requires size of ~s to be known"), self, carray, nao);
}
-static void carray_ensure_artype(val carray, struct carray *scry, val self)
+static void carray_ensure_artype(val carray, struct carray *scry, int null_term, val self)
{
- if (!scry->artype) {
+ if (!scry->artype[null_term]) {
val dim = num(scry->nelem);
- val syntax = list(carray_s, dim, scry->eltft->syntax, nao);
+ val syntax = if3(scry->nelem < 0,
+ list(carray_s, scry->eltft->syntax, nao),
+ list(carray_s, dim, scry->eltft->syntax, nao));
struct txr_ffi_type *etft = scry->eltft;
- set(mkloc(scry->artype, carray), make_ffi_type_array(syntax, vec_s,
- dim, scry->eltype,
- self));
+ set(mkloc(scry->artype[null_term], carray),
+ make_ffi_type_array(syntax, vec_s,
+ dim, scry->eltype,
+ self));
{
- struct txr_ffi_type *atft = ffi_type_struct(scry->artype);
+ struct txr_ffi_type *atft = ffi_type_struct(scry->artype[null_term]);
+
if (etft->syntax == char_s)
atft->ch_conv = conv_char;
else if (etft->syntax == wchar_s)
atft->ch_conv = conv_wchar;
else if (etft->syntax == bchar_s)
atft->ch_conv = conv_bchar;
+
+ atft->null_term = null_term;
}
}
}
@@ -5660,11 +5696,10 @@ static val carray_get_common(val carray, val self, unsigned null_term)
{
struct carray *scry = carray_struct_checked(self, carray);
- carray_ensure_artype(carray, scry, self);
+ carray_ensure_artype(carray, scry, null_term, self);
{
- struct txr_ffi_type *atft = ffi_type_struct(scry->artype);
- atft->null_term = null_term;
+ struct txr_ffi_type *atft = ffi_type_struct(scry->artype[null_term]);
return atft->get(atft, scry->data, self);
}
}
@@ -5673,11 +5708,10 @@ static void carray_put_common(val carray, val seq, val self, unsigned null_term)
{
struct carray *scry = carray_struct_checked(self, carray);
- carray_ensure_artype(carray, scry, self);
+ carray_ensure_artype(carray, scry, null_term, self);
{
- struct txr_ffi_type *atft = ffi_type_struct(scry->artype);
- atft->null_term = null_term;
+ struct txr_ffi_type *atft = ffi_type_struct(scry->artype[null_term]);
return atft->put(atft, seq, scry->data, self);
}
}