mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-03-09 06:30:32 -07:00
The compiler was coercing base strings to extended strings when encountering them as literal objects in compiled files. According to CLHS 3.2.4.2.2, we need to preserve the actual element type (after upgrading) of arrays during compilation. For ECL, the actual array element type of a base-string is base-char and therefore we can't change this to an extended string. Actually fixing this requires some work since we use the reader to store a printed representation of the string in the compiled file. The reader string syntax always returns an extended string (There is a comment in the code which claims that this is implied by CLHS 2.4.5. I am not quite sure if that is really true but for backwards compatibility I don't want to change this). We thus introduce a new syntax #"..." for base strings which is used when reading objects from compiled files. To prevent the new syntax from leaking outside of this context, we also introduce a new readtable.
211 lines
5.5 KiB
C
211 lines
5.5 KiB
C
/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
|
|
|
|
/*
|
|
* write_array.d - file interface
|
|
*
|
|
* Copyright (c) 1984 Taiichi Yuasa and Masami Hagiya
|
|
* Copyright (c) 1990 Giuseppe Attardi
|
|
* Copyright (c) 2001 Juan Jose Garcia Ripoll
|
|
*
|
|
* See file 'LICENSE' for the copyright details.
|
|
*
|
|
*/
|
|
|
|
#include <ecl/ecl.h>
|
|
#include <ecl/internal.h>
|
|
|
|
static void
|
|
write_array_inner(bool vector, cl_object x, cl_object stream)
|
|
{
|
|
cl_env_ptr env = ecl_process_env();
|
|
const cl_index *adims;
|
|
cl_index subscripts[ECL_ARRAY_RANK_LIMIT];
|
|
cl_fixnum n, j, m, k, i;
|
|
cl_fixnum print_length;
|
|
cl_fixnum print_level;
|
|
bool readably = ecl_print_readably();
|
|
|
|
if (vector) {
|
|
adims = &x->vector.fillp;
|
|
n = 1;
|
|
} else {
|
|
adims = x->array.dims;
|
|
n = x->array.rank;
|
|
}
|
|
if (readably) {
|
|
print_length = MOST_POSITIVE_FIXNUM;
|
|
print_level = MOST_POSITIVE_FIXNUM;
|
|
} else {
|
|
if (!ecl_print_array()) {
|
|
writestr_stream(vector? "#<vector " : "#<array ", stream);
|
|
_ecl_write_addr((void *)x, stream);
|
|
ecl_write_char('>', stream);
|
|
return;
|
|
}
|
|
print_level = ecl_print_level();
|
|
print_length = ecl_print_length();
|
|
}
|
|
ecl_write_char('#', stream);
|
|
if (print_level == 0)
|
|
return;
|
|
if (readably) {
|
|
ecl_write_char('A', stream);
|
|
ecl_write_char('(', stream);
|
|
si_write_object(ecl_elttype_to_symbol(ecl_array_elttype(x)), stream);
|
|
ecl_write_char(' ', stream);
|
|
if (n > 0) {
|
|
ecl_write_char('(', stream);
|
|
for (j=0; j<n; j++) {
|
|
si_write_object(ecl_make_fixnum(adims[j]), stream);
|
|
if (j < n-1)
|
|
ecl_write_char(' ', stream);
|
|
}
|
|
ecl_write_char(')', stream);
|
|
} else {
|
|
si_write_object(ECL_NIL, stream);
|
|
}
|
|
ecl_write_char(' ', stream);
|
|
} else if (!vector) {
|
|
_ecl_write_fixnum(n, stream);
|
|
ecl_write_char('A', stream);
|
|
}
|
|
if (print_level >= n) {
|
|
/* We can write the elements of the array */
|
|
print_level -= n;
|
|
ecl_bds_bind(env, @'*print-level*', ecl_make_fixnum(print_level));
|
|
} else {
|
|
/* The elements of the array are not printed */
|
|
n = print_level;
|
|
print_level = -1;
|
|
}
|
|
for (j = 0; j < n; j++)
|
|
subscripts[j] = 0;
|
|
for (m = 0, j = 0;;) {
|
|
for (i = j; i < n; i++) {
|
|
if (subscripts[i] == 0) {
|
|
ecl_write_char('(', stream);
|
|
if (adims[i] == 0) {
|
|
ecl_write_char(')', stream);
|
|
j = i-1;
|
|
k = 0;
|
|
goto INC;
|
|
}
|
|
}
|
|
if (subscripts[i] > 0)
|
|
ecl_write_char(' ', stream);
|
|
if (subscripts[i] >= print_length) {
|
|
writestr_stream("...)", stream);
|
|
k=adims[i]-subscripts[i];
|
|
subscripts[i] = 0;
|
|
for (j = i+1; j < n; j++)
|
|
k *= adims[j];
|
|
j = i-1;
|
|
goto INC;
|
|
}
|
|
}
|
|
/* FIXME: This conses! */
|
|
if (print_level >= 0)
|
|
si_write_object(ecl_aref_unsafe(x, m), stream);
|
|
else
|
|
ecl_write_char('#', stream);
|
|
j = n-1;
|
|
k = 1;
|
|
|
|
INC:
|
|
while (j >= 0) {
|
|
if (++subscripts[j] < adims[j])
|
|
break;
|
|
subscripts[j] = 0;
|
|
ecl_write_char(')', stream);
|
|
--j;
|
|
}
|
|
if (j < 0)
|
|
break;
|
|
m += k;
|
|
}
|
|
if (print_level >= 0) {
|
|
ecl_bds_unwind1(env);
|
|
}
|
|
if (readably) {
|
|
ecl_write_char(')', stream);
|
|
}
|
|
}
|
|
|
|
void
|
|
_ecl_write_array(cl_object x, cl_object stream)
|
|
{
|
|
write_array_inner(0, x, stream);
|
|
}
|
|
|
|
void
|
|
_ecl_write_vector(cl_object x, cl_object stream)
|
|
{
|
|
write_array_inner(1, x, stream);
|
|
}
|
|
|
|
#ifdef ECL_UNICODE
|
|
void
|
|
_ecl_write_string(cl_object x, cl_object stream)
|
|
{
|
|
if (!ecl_print_escape() && !ecl_print_readably()) {
|
|
si_do_write_sequence(x, stream, ecl_make_fixnum(0), ECL_NIL);
|
|
} else {
|
|
cl_index ndx, ndx_start;
|
|
ecl_write_char('"', stream);
|
|
for (ndx = ndx_start = 0; ndx < x->string.fillp; ndx++) {
|
|
ecl_character c = x->string.self[ndx];
|
|
if (c == '"' || c == '\\') {
|
|
si_do_write_sequence(x, stream, ecl_make_fixnum(ndx_start), ecl_make_fixnum(ndx));
|
|
ecl_write_char('\\', stream);
|
|
ndx_start = ndx;
|
|
}
|
|
}
|
|
si_do_write_sequence(x, stream, ecl_make_fixnum(ndx_start), ECL_NIL);
|
|
ecl_write_char('"', stream);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void
|
|
_ecl_write_base_string(cl_object x, cl_object stream)
|
|
{
|
|
if (!ecl_print_escape() && !ecl_print_readably()) {
|
|
si_do_write_sequence(x, stream, ecl_make_fixnum(0), ECL_NIL);
|
|
} else {
|
|
if (ecl_symbol_value(@'*print-array*') == @'base-string') {
|
|
/* Base string syntax used for data in compiled files. */
|
|
ecl_write_char('#', stream);
|
|
}
|
|
cl_index ndx, ndx_start;
|
|
ecl_write_char('"', stream);
|
|
for (ndx = ndx_start = 0; ndx < x->base_string.fillp; ndx++) {
|
|
ecl_character c = x->base_string.self[ndx];
|
|
if (c == '"' || c == '\\') {
|
|
si_do_write_sequence(x, stream, ecl_make_fixnum(ndx_start), ecl_make_fixnum(ndx));
|
|
ecl_write_char('\\', stream);
|
|
ndx_start = ndx;
|
|
}
|
|
}
|
|
si_do_write_sequence(x, stream, ecl_make_fixnum(ndx_start), ECL_NIL);
|
|
ecl_write_char('"', stream);
|
|
}
|
|
}
|
|
|
|
void
|
|
_ecl_write_bitvector(cl_object x, cl_object stream)
|
|
{
|
|
if (!ecl_print_array() && !ecl_print_readably()) {
|
|
writestr_stream("#<bit-vector ", stream);
|
|
_ecl_write_addr((void *)x, stream);
|
|
ecl_write_char('>', stream);
|
|
} else {
|
|
cl_index ndx;
|
|
writestr_stream("#*", stream);
|
|
for (ndx = 0; ndx < x->vector.fillp; ndx++)
|
|
if (x->vector.self.bit[(ndx+x->vector.offset)/8] & (0200 >> (ndx+x->vector.offset)%8))
|
|
ecl_write_char('1', stream);
|
|
else
|
|
ecl_write_char('0', stream);
|
|
}
|
|
}
|