From dfafb4879c1e65657ad89232e57f60c7a07f8c66 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 17 Jan 2019 01:42:29 -0800 Subject: carray: fix vec/list conversion bug. If a zero-length carray is converted with vec-carray or list-carray and the null-term-p argument is t, there is an exception about a negative index. An empty vector or list should be returned in this case, and the documentation says exactly that. Also, if a carray of unknown length is converted, there is an exception from vec-carray, as documented, but it's an uninformative one that is incidentally produced when -1 is passed to the vec function. The list-carray just returns nil, contravening the documentation. * ffi.c (vec_carray, list_carray): Fix the problems described above. * txr.1: Reviewing the documentation for these functions, an improperly terminated sentence was found. --- ffi.c | 42 ++++++++++++++++++++++++++++++------------ txr.1 | 2 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/ffi.c b/ffi.c index b1f00d76..07e361ae 100644 --- a/ffi.c +++ b/ffi.c @@ -4887,13 +4887,22 @@ val vec_carray(val carray, val null_term_p) val nt_p = default_null_arg(null_term_p); struct carray *scry = carray_struct_checked(self, carray); cnum i, l = if3(nt_p, scry->nelem - 1, scry->nelem); - val vec = vector(num(l), nil); - for (i = 0; i < l; i++) { - val ni = num_fast(i); - val el = carray_ref(carray, ni); - set(vecref_l(vec, ni), el); + + if (l >= 0) { + val vec = vector(num(l), nil); + for (i = 0; i < l; i++) { + val ni = num_fast(i); + val el = carray_ref(carray, ni); + set(vecref_l(vec, ni), el); + } + return vec; + } else if (scry->nelem >= 0) { + return vector(zero, nil); + } else { + uw_throwf(error_s, + lit("~a: cannot convert unknown length carray to vector"), + self, nao); } - return vec; } val list_carray(val carray, val null_term_p) @@ -4902,13 +4911,22 @@ val list_carray(val carray, val null_term_p) val nt_p = default_null_arg(null_term_p); struct carray *scry = carray_struct_checked(self, carray); cnum i, l = if3(nt_p, scry->nelem - 1, scry->nelem); - list_collect_decl (list, ptail); - for (i = 0; i < l; i++) { - val ni = num_fast(i); - val el = carray_ref(carray, ni); - ptail = list_collect(ptail, el); + + if (l >= 0) { + list_collect_decl (list, ptail); + for (i = 0; i < l; i++) { + val ni = num_fast(i); + val el = carray_ref(carray, ni); + ptail = list_collect(ptail, el); + } + return list; + } else if (scry->nelem >= 0) { + return nil; + } else { + uw_throwf(error_s, + lit("~a: cannot convert unknown length carray to list"), + self, nao); } - return list; } val carray_ref(val carray, val idx) diff --git a/txr.1 b/txr.1 index 7014d37e..861bb2af 100644 --- a/txr.1 +++ b/txr.1 @@ -62519,7 +62519,7 @@ and a zero-length vector or list is returned. Conversion of the foreign array to the vector or list is performed by iterating over all of its elements, starting from element zero, up to the -element before the effective length, +element before the effective length. .coNP Functions @ carray-get and @ carray-getz .synb -- cgit v1.2.3