* libguile/ports.c (peek_iconv_codepoint): If the input has no bytes,
there's little point in raising a decoding error here. Therefore remove
the needless iconv acquisition, harmonising with suspendable-ports.
* test-suite/tests/ports.test ("port-encoding"): Update test to include
some input so that the exception gets raised.
* libguile/bytevectors.c (INTEGER_ACCESSOR_PROLOGUE)
(scm_bytevector_copy_x, bytevector_large_set): Rewrite checks to reliably
detect overflows.
(make_bytevector): Constrain the bytevector length to avoid later
overflows during allocation.
(make_bytevector_from_buffer): Fix indentation.
(scm_bytevector_length): Use 'scm_from_size_t' to convert a 'size_t',
not 'scm_from_uint'.
* libguile/fports.c (fport_seek): Check for overflow before the implicit
conversion of the return value.
* libguile/guardians.c (guardian_print): Use 'scm_from_ulong' to convert
an 'unsigned long', not 'scm_from_uint'.
* libguile/ports.c (scm_unread_string): Change a variable to type 'size_t'.
(scm_seek, scm_truncate_file): Use 'scm_t_off' instead of
'off_t_or_off64_t' to avoid implicit type conversions that could
overflow, because 'ptob->seek' and 'ptob->truncate' use 'scm_t_off'.
* libguile/r6rs-ports.c (bytevector_input_port_seek)
(custom_binary_port_seek, bytevector_output_port_seek): Rewrite offset
calculations to reliably detect overflows. Use 'scm_from_off_t' to
convert a 'scm_t_off', not 'scm_from_long' nor 'scm_from_int'.
(scm_get_bytevector_n_x, scm_get_bytevector_all, scm_unget_bytevector)
(bytevector_output_port_write): Rewrite checks to reliably detect
overflows. Use 'size_t' where appropriate.
(bytevector_output_port_buffer_grow): Rewrite size calculations to
reliably detect overflows. Minor change in the calculation of the new
size: now it is max(min_size, 2*current_size), whereas previously it
would multiply current_size by the smallest power of 2 needed to surpass
min_size.
* libguile/strings.c (make_stringbuf): Constrain the stringbuf length to
avoid later overflows during allocation.
(scm_string_append): Change overflow check to use INT_ADD_OVERFLOW.
* libguile/strports.c (string_port_write): Rewrite size calculations to
reliably detect overflows.
(string_port_seek): Rewrite offset calculations to reliably detect
overflows. Use 'scm_from_off_t' to convert a 'scm_t_off', not
'scm_from_long'.
(string_port_truncate): Use 'scm_from_off_t' to convert a 'scm_t_off',
not 'scm_from_off_t_or_off64_t'.
* libguile/vectors.c (scm_c_make_vector): Change a variable to type
'size_t'.
This reverts the change to SCM_MAKE_CHAR made in the previous commit
63818453ad, which used an arithmetic trick
to avoid evaluating its argument more than once.
Here, we restore the previous implementation of SCM_MAKE_CHAR, which
evaluates its argument twice. Instead, we introduce a new inlinable
function 'scm_c_make_char' and replace uses of SCM_MAKE_CHAR with calls
to 'scm_c_make_char' where appropriate.
* libguile/chars.h (scm_c_make_char): New inline function.
* libguile/inline.c: Include chars.h.
* libguile/srfi-13.c (REF_IN_CHARSET, scm_string_any, scm_string_every)
(scm_string_trim, scm_string_trim_right, scm_string_trim_both)
(scm_string_index, scm_string_index_right, scm_string_skip)
(scm_string_skip_right, scm_string_count, string_titlecase_x)
(string_reverse_x, scm_string_fold, scm_string_fold_right)
(scm_string_for_each, scm_string_filter, scm_string_delete):
Use 'scm_c_make_char' instead of 'SCM_MAKE_CHAR' in cases where the
argument calls a function.
* libguile/chars.c (scm_char_upcase, scm_char_downcase, scm_char_titlecase),
libguile/ports.c (scm_port_decode_char),
libguile/print.c (scm_simple_format),
libguile/read.c (scm_read_character),
libguile/strings.c (scm_string_ref, scm_c_string_ref),
This reverts the change to SCM_MAKE_CHAR made in the previous commit
63818453ad, which used an arithmetic trick
to avoid evaluating its argument more than once.
Here, we restore the previous implementation of SCM_MAKE_CHAR, which
evaluates its argument twice. Instead, we introduce a new inlinable
function 'scm_c_make_char' and replace uses of SCM_MAKE_CHAR with calls
to 'scm_c_make_char' where appropriate.
* libguile/chars.h (scm_c_make_char): New inline function.
* libguile/inline.c: Include chars.h.
* libguile/srfi-13.c (REF_IN_CHARSET, scm_string_any, scm_string_every)
(scm_string_trim, scm_string_trim_right, scm_string_trim_both)
(scm_string_index, scm_string_index_right, scm_string_skip)
(scm_string_skip_right, scm_string_count, string_titlecase_x)
(string_reverse_x, scm_string_fold, scm_string_fold_right)
(scm_string_for_each, scm_string_filter, scm_string_delete):
Use 'scm_c_make_char' instead of 'SCM_MAKE_CHAR' in cases where the
argument calls a function.
* libguile/chars.c (scm_char_upcase, scm_char_downcase, scm_char_titlecase),
libguile/ports.c (scm_port_decode_char),
libguile/print.c (scm_simple_format),
libguile/read.c (scm_read_character),
libguile/strings.c (scm_string_ref, scm_c_string_ref),
libguile/vm-engine.c ("string-ref"): Ditto.
As the FSF advises, 'There is no legal significance to using the
three-character sequence “(C)”, but it does no harm.' It does take up
space though! For that reason, we remove it here from our C files.
* libguile/bytevectors.h: Include uniform.h, for use in the macros.
* libguile/extensions.h: Include libpath.h, for the
SCM_EFFECTIVE_VERSION, which is almost always used with these
routines.
* libguile/frames.h:
* libguile/instructions.h:
* libguile/intrinsics.h:
* libguile/loader.h:
* libguile/programs.h:
* libguile/vm.h: Include <libguile/__scm.h> instead of <libguile.h>.
Cuts a circular include, but also precipitates a lot of maintenance in
the .c files.
* libguile/*.c: Update C files to add needed all needed includes that
before were getting automatically pulled in by the indirect inclusion
of libguile.h.
Reported at <https://bugs.gnu.org/28784>.
Discussed at
<https://lists.gnu.org/archive/html/guile-devel/2017-10/msg00003.html>.
* libguile/fports.c (revealed_ports, revealed_lock): Remove.
(scm_revealed_count): Just return 'SCM_REVEALED (port)'.
(scm_set_port_revealed_x, scm_adjust_port_revealed_x): Remove
REVEALED_PORTS manipulation.
(fport_close): Do nothing when SCM_REVEALED (port) > 0.
* libguile/fports.h (scm_t_fport): Adjust comment; make 'revealed'
unsigned.
* libguile/ports.c (do_close): Call 'close_port' instead of
'scm_close_port'.
(scm_close_port): Rename to...
(close_port): ... this. Add 'explicit' parameter. Clear 'revealed'
field when PORT is a file port and EXPLICIT is true.
(scm_close_port): Call 'close_port'.
* test-suite/tests/ports.test ("close-port & revealed port")
("revealed port fdes not closed"): New tests.
* libguile/ports-internal.h (scm_port_buffer_can_take):
(scm_port_buffer_can_put): Add cur/end output arguments so that when a
caller asks the buffer room, it can be relative to a fixed point in
the buffer and not whatever point it's at when we go to fill it.
(scm_port_buffer_did_take, scm_port_buffer_did_put): Similarly,
require that the caller knows where they took/put data in the buffer.
Prevents overflow.
(scm_port_buffer_take_pointer, scm_port_buffer_put_pointer): Likewise,
require that the caller has already checked and knows a position in
the buffer and therefore how much data is available.
(scm_port_buffer_take, scm_port_buffer_put, scm_port_buffer_putback):
Adapt.
* libguile/ports.h (scm_fill_input): Add cur/avail output arguments.
* libguile/filesys.c:
* libguile/poll.c:
* libguile/ports.c:
* libguile/r6rs-ports.c:
* libguile/read.c:
* libguile/rw.c: Adapt all callers. Gnarly work!
* libguile/root.h:
* libguile/root.c: Remove these files.
* libguile/deprecated.h:
* libguile/deprecated.c (scm_internal_cwdr, scm_call_with_dynamic_root)
(scm_dynamic_root, scm_apply_with_dynamic_root): Deprecate.
Remove all root.h usage, which was vestigial.
* module/ice-9/serialize.scm: Use (current-thread) instead
of (dynamic-root).
* libguile/ports.h (SCM_F_PORT_FINALIZING)
(SCM_PORT_FINALIZING_P, SCM_SET_PORT_FINALIZING): New private
definitions.
* libguile/ports.c (finalize_port): Set the port-finalizing flag.
(scm_i_write_bytes): If the port is finalizing but output returned
EWOULDBLOCK, warn and discard the output.
* libguile/ports.c (scm_seek): Avoid flushing buffers for an ftell.
Also allows non-random-access ports to ftell() if they have a seek
implementation, as is the case for custom binary ports with a
get-position function but no set-position function.
* test-suite/tests/ports.test: Adapt expectations, reverting changes
made in April by me in b77fb752dd.
* libguile/ports.c (scm_init_ports): Use the locale as the default
charset. After the switch to default GUILE_INSTALL_LOCALE=1, this
harmonizes the default port encoding with the installed locale.
* libguile/ports.c (scm_setvbuf): Fix bad use of SCM as a test value.
Actually all ports have read buffers, so we can remove the condition
entirely. Thanks Hydra for building in this way :)
* libguile/ports.c (scm_port_encode_char): New function.
* module/ice-9/ports.scm (port-encode-char): Export port-encode-char to
the internals module.
* module/ice-9/sports.scm (put-char): New function.
(port-bindings): Add put-char and put-string.
* libguile/ports.h (scm_put_char):
* libguile/ports.c (scm_put_char): New function.
(scm_put_string): Add docstrings, and expose to the internal ports
module.
* module/ice-9/ports.scm (put-char, put-string): Expose these bindings
only through the internals module.
* libguile/ports.c (scm_port_clear_stream_start_for_bom_write): Instead
of returning the BOM, take an optional buffer in which to write the
BOM. Return number of bytes written.
(port_clear_stream_start_for_bom_write): Remove.
(scm_i_write): Adapt scm_port_clear_stream_start_for_bom_write call.
(try_encode_char_to_iconv_buf, encode_latin1_chars_to_latin1_buf):
(encode_latin1_chars_to_utf8_buf, encode_latin1_chars_to_iconv_buf):
(encode_latin1_chars, encode_utf32_chars_to_latin1_buf):
(encode_utf32_chars_to_utf8_buf, encode_utf32_chars_to_iconv_buf):
(encode_utf32_chars, port_encode_chars): New helpers.
(scm_port_encode_chars): New procedure.
(scm_c_put_latin1_chars, scm_c_put_utf32_chars): Rework to use new
encoding helpers.
(scm_lfwrite): Use scm_c_put_latin1_chars.
* libguile/ports.h (scm_c_put_latin1_chars, scm_c_put_utf32_chars)
(scm_c_put_char, scm_c_put_string, scm_print_string): New public
functions. The plan is to move encoding to ports.c and out of
print.c.
* libguile/ports.c (UTF8_BUFFER_SIZE, ESCAPE_BUFFER_SIZE): New internal
defines.
(update_port_position): Take a position instead of a port. Update
callers.
(utf8_to_codepoint): Allow lengths that are larger than necessary.
(port_clear_stream_start_for_bom_write): Require that io_mode be
BOM_IO_TEXT to write a BOM.
(scm_fill_input): Add a related comment about BOM handling.
(scm_i_write): use BOM_IO_TEXT, at least for now.
(encode_escape_sequence, codepoint_to_utf8, utf8_to_codepoint)
(put_utf8_chars_to_iconv_port, put_latin1_chars_to_utf8_port)
(put_latin1_chars_to_iconv_port, put_utf32_chars_to_latin1_port)
(put_utf32_chars_to_utf8_port, put_utf32_chars_to_iconv_port): New
helpers.
(scm_putc, scm_puts): Use scm_c_put_char and scm_put_latin1_chars.
* libguile/ports.c (scm_port_line_buffered_p): New function.
* module/ice-9/ports.scm: Plump port-line-buffered? and
port-auxiliary-write-buffer through to the internals module
* libguile/ports-internal.h (scm_t_port): Add write_buf_aux field.
* libguile/ports.h (scm_port_auxiliary_write_buffer): New internal
decl.
* libguile/ports.c (AUXILIARY_WRITE_BUFFER_SIZE): New constant.
(initialize_port_buffers): Init aux write buf.
(scm_port_auxiliary_write_buffer): Lazily allocate an aux write
buffer.
(scm_c_write): Arrange to write through an aux buffer if the port is
unbuffered.