String pointer arrays
Add a special built-in armor type for null-terminated arrays of pointers to null-terminated C strings. In other words, each C string is terminated by the null character
\0, and the array itself is terminated by the null pointer (address 0).
The wrapper procedure should by default detect the array length by scanning for a null pointer. The array length should not include the final null pointer. The caller should be able to explicitly pass an array length, to handle cases where an array has unused capacity. A newly allocated string array should be initialized to null pointers.
Scheme strings in CHICKEN cannot refer to a C string in static memory, so the array item getters and setters must necessarily perform copying. In other words, the getter must return a new Scheme string that is a copy of the C string at the array index, and the setter must set the array index to a new C string that is a copy of the given Scheme string.
(The alternative to copying would be to implement an armor type that wraps a C string pointer. But this armor type would not be compatible with any Scheme procedure that expects a string, so it is not useful, and would probably be a source of confusion and frustration for users.)
The setter procedure should free the existing string at the array index, if there is one. Passing #f to the setter should set that index to the null pointer.
Include helper procedures for converting a Scheme list or vector of Scheme strings into a string pointer array, and vice versa.
Example use cases:
- libpq (PostgreSQL's C API) uses null-terminated arrays of null-terminated strings in several places, including
tcc_runaccepts a string array for
int tcc_run(TCCState *s, int argc, char **argv). This array does not need to be a null-terminated because the function also takes an
argcargument, but a null-terminated array would work.
- Many libraries have functions that accept a
char **argument which the library may set to a string that it has allocated. Semantically this is not really a string pointer array, but using a string pointer array makes this use case easy to handle: allocate and pass a string pointer array of length 1, then use the array item getter to get the string as a Scheme string.