1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 04:10:18 +02:00
Commit graph

466 commits

Author SHA1 Message Date
Ludovic Courtès
659526d33b ports: 'scm_port_poll' honors "w" flags.
Fixes <https://bugs.gnu.org/36709>.
Reported by Mark H Weaver <mhw@netris.org>.

* libguile/ports.c (scm_port_poll): Replace second POLLIN by POLLOUT.
2019-11-18 15:14:56 +01:00
Mark H Weaver
579dd2da44 Rename 'scm_c_make_char' to 'scm_i_make_char'.
* libguile/chars.c, libguile/chars.h, libguile/ports.c,
libguile/print.c, libguile/read.c, libguile/srfi-13.c,
libguile/strings.c, libguile/vm-engine.c: Rename 'scm_c_make_char' to
'scm_i_make_char'.
2019-06-18 07:30:54 -04:00
Mark H Weaver
91ba73b397 Improve overflow checks in bytevector, string, and I/O operations.
* 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'.
2019-06-18 02:05:20 -04:00
Mark H Weaver
2a1f22c00a Add 'scm_c_make_char' and use it where appropriate.
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.
2019-05-07 04:37:52 -04:00
Ludovic Courtès
1008ea3154 Allow garbage collection of revealed file ports.
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.
2017-10-25 11:39:38 -07:00
Andy Wingo
f71c2c1260 Micro-optimize update-port-position.
* libguile/ports.c (update_port_position): Only fetch line if we need to
  increment it.
2017-03-09 17:24:06 +01:00
Andy Wingo
25652ff84c %port-encoding requires an open port
* libguile/ports.c (scm_sys_port_encoding)
  (scm_sys_set_port_encoding_x): Require an open port, to match 2.0
  behavior.
2017-03-01 19:52:17 +01:00
Andy Wingo
09a69dd712 Prevent TOCTTOU bugs in C ports
* 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!
2017-02-08 15:09:14 +01:00
Andy Wingo
b392d81c9c Fix close-port race.
* libguile/ports.c (release_port): Fix race.
2017-01-08 15:42:22 +01:00
Andy Wingo
dc2a560264 Deprecate dynamic roots
* 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).
2016-11-21 23:09:21 +01:00
Andy Wingo
b733ca461c GC of non-blocking port does not block
* 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.
2016-08-31 19:31:12 +02:00
Andy Wingo
b8a53b98b3 Only ptob->close() after read/write finish
* libguile/Makefile.am (noinst_HEADERS): Add atomics-internal.h.
* libguile/atomics-internal.h: New file.
* libguile/ports-internal.h (refcount): New member.
* libguile/ports.c (release_port, scm_dynwind_acquire_port): New
  facility for acquiring a port within a dynwind.
  (scm_port_poll, scm_i_read_bytes, scm_setvbuf, scm_end_input)
  (scm_i_write_bytes, scm_char_ready_p, scm_seek)
  (scm_truncate_file, trampoline_to_c_read)
  (trampoline_to_c_write): Acquire port.
  (scm_c_make_port_with_encoding): Init refcount to 1.
  (scm_close_port): Release port.
* doc/ref/api-io.texi (I/O Extensions): Add documentation
2016-08-31 19:10:35 +02:00
Andy Wingo
eeb23e776a Avoid flushing buffers for ftell
* 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.
2016-08-31 15:39:01 +02:00
Andy Wingo
f23dfc0fb5 Locale is default port encoding
* 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.
2016-06-24 07:43:58 +02:00
Andy Wingo
3abd8e1ac1 Fix SCM_DEBUG_TYPING_STRICTNESS bug
* 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 :)
2016-06-22 12:50:16 +02:00
Andy Wingo
0c1ee6eae6 Fix ports bug when size_t is 32 bits
* libguile/ports.c (scm_end_input): I am a complete idiot.  I had no
  idea that `- (uint32_t) x' is actually still a uint32_t.
2016-06-18 13:08:12 +02:00
Andy Wingo
d8067213dc put-char in Scheme
* 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.
2016-06-09 10:59:02 +02:00
Andy Wingo
4bceba876b put-char, put-string in (ice-9 ports internals)
* 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.
2016-06-08 07:44:16 +02:00
Andy Wingo
5bec3261b4 Rework text encoding to be more Scheme-friendly
* 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.
2016-06-01 12:07:20 +02:00
Andy Wingo
2affb9accf Add scm_c_put_escaped_char, scm_c_can_put_char
* libguile/ports.h:
* libguile/ports.c (scm_c_put_escaped_char, scm_c_can_put_char): New
  helpers.
2016-05-30 18:48:09 +02:00
Andy Wingo
43b6feeb1a Beginnings of supporting encoding text in ports.c
* 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.
2016-05-30 15:06:38 +02:00
Andy Wingo
1123002a9e Add port-line-buffered?
* 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
2016-05-25 21:56:19 +02:00
Andy Wingo
2f836e2384 port_clear_stream_start_for_bom_write refactor
* libguile/ports.c (port_clear_stream_start_for_bom_write): Rework to be
  friendly to Scheme write implementations.
2016-05-25 21:56:16 +02:00
Andy Wingo
47918f38d9 Speed up scm_c_write / scm_lfwrite
* 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.
2016-05-24 22:44:48 +02:00
Andy Wingo
6bf7ec0c9c Thread-safety fixes for iconv and ports
* libguile/ports-internal.h (scm_t_port): Rework to store iconv
  descriptors inline, so that the port finalizer doesn't race with the
  iconv descriptor finalizer.  Access is serialized through a lock.
  Fixes a bug whereby if the port finalizer and the descriptor finalizer
  run on different threads, the close-port run by the port finalizer
  could try to free the iconv descriptors at the same time as the
  descriptor finalizer.
* libguile/ports.c (iconv_lock): New static variable.
  (scm_c_make_port_with_encoding): Initialize iconv-related fields.
  (scm_close_port): Lock while frobbing iconv descriptors.
  (prepare_iconv_descriptors): Adapt.
  (scm_specialize_port_encoding_x, scm_i_set_port_encoding_x): Lock
  while preparing iconv descriptors.
  (scm_port_acquire_iconv_descriptors)
  (scm_port_release_iconv_descriptors): New functions, which replace
  scm_i_port_iconv_descriptors.
  (scm_port_decode_char): Lock around iconv operations.
  (port_clear_stream_start_for_bom_write): Acquire iconv descriptors
  before checking precise_encoding, to make sure precise_encoding is
  initialized.
* libguile/print.c (display_string_using_iconv): Adapt to use the new
  interface to get iconv descriptors from a port.
2016-05-23 16:37:23 +02:00
Andy Wingo
4e288ec2ff Fix range checking in new Scheme-to-C port code
* libguile/ports.c (trampoline_to_c_read, trampoline_to_c_write): Fix
  bugs checking ranges of start and count parameters.
2016-05-22 22:33:46 +02:00
Andy Wingo
fd17cf9f72 Speed up port position access from Scheme
* libguile/ports-internal.h (scm_port_buffer_position):
  (scm_port_position_line, scm_port_position_set_line):
  (scm_port_position_column, scm_port_position_set_column): New
  helpers.
  (scm_t_port): Ports now hold position as a pair, so that Scheme can
  access it easily.
  (SCM_LINUM, SCM_COL, SCM_INCLINE, SCM_ZEROCOL, SCM_INCCOL)
  (SCM_DECCOL, SCM_TABCOL): Remove.
* libguile/ports.c (make_port_buffer): Rename from
  scm_c_make_port_buffer, make static, and take port as an argument so
  we can initialize the position field.
  (initialize_port_buffers): Adapt make_port_buffer change.
  (scm_c_make_port_with_encoding): Initialize position.
  (update_port_position): Rename from update_port_lf, and operate on
  port position objects.
  (scm_ungetc): Operate on port position objects.
  (scm_setvbuf, scm_expand_port_read_buffer_x): Adapt to
  make_port_buffer change.
  (scm_lfwrite): Adapt to call update_port_position.
  (scm_port_line, scm_set_port_line_x, scm_port_column)
  (scm_set_port_column_x): Adapt to use port positions.
* libguile/ports.h (scm_c_make_port_buffer): Remove internal decl.
* libguile/read.c: Adapt to use scm_port_line / scm_port_column instead
  of SCM_LINUM et al.
* module/ice-9/ports.scm (port-buffer-position, port-position-line)
  (port-position-column, set-port-position-line!)
  (set-port-position-column!): New accessors for the internals module.
* module/ice-9/sports.scm (advance-port-position!): Rename from
  port-advance-position! and use the new accessors.
  (read-char, port-fold-chars/iso-8859-1): Adapt to use
  advance-port-position!.
2016-05-22 18:16:19 +02:00
Andy Wingo
534139e458 Support for non-blocking I/O
* doc/ref/api-io.texi (I/O Extensions): Document read_wait_fd /
  write_wait_fd members.
  (Non-Blocking I/O): New section.
* libguile/fports.c (fport_read, fport_write): Return -1 if the
  operation would block.
  (fport_wait_fd, scm_make_fptob): Add read/write wait-fd
  implementation.
* libguile/ports-internal.h (scm_t_port_type): Add read_wait_fd /
  write_wait_fd.
* libguile/ports.c (default_read_wait_fd, default_write_wait_fd): New
  functions.
  (scm_make_port_type): Initialize default read/write wait fd impls.
  (trampoline_to_c_read, trampoline_to_scm_read)
  (trampoline_to_c_write, trampoline_to_scm_write): To Scheme, a return
  of #f indicates EWOULDBLOCk.
  (scm_set_port_read_wait_fd, scm_set_port_write_wait_fd): New
  functions.
  (port_read_wait_fd, port_write_wait_fd, scm_port_read_wait_fd)
  (scm_port_write_wait_fd, port_poll, scm_port_poll): New functions.
  (scm_i_read_bytes, scm_i_write_bytes): Poll if the read or write would
  block.
* libguile/ports.h (scm_set_port_read_wait_fd)
  (scm_set_port_write_wait_fd): Add declarations.
* module/ice-9/ports.scm: Shunt port-poll and port-{read,write}-wait-fd
  to the internals module.
* module/ice-9/sports.scm (current-write-waiter):
  (current-read-waiter): Implement.
* test-suite/tests/ports.test: Adapt non-blocking test to new behavior.
* NEWS: Add entry.
2016-05-20 14:57:27 +02:00
Andy Wingo
1e058add7b U+FFFD is the input substitution character
* libguile/ports.c (UNICODE_REPLACEMENT_CHARACTER):
* libguile/ports.c (peek_utf8_codepoint)
  (scm_port_decode_char, peek_iconv_codepoint):
* module/ice-9/sports.scm (peek-char-and-len/utf8):
  (peek-char-and-len/iconv): Return U+FFFD when we get a decoding error
  when reading, instead of '?', in accordance with Unicode
  recommendations.
* test-suite/tests/iconv.test:
* test-suite/tests/ports.test:
* test-suite/tests/rdelim.test: Update tests.
* NEWS: Update.
2016-05-16 10:48:35 +02:00
Andy Wingo
9ecf77a82d Add SCM_OPN to mode bits when making ports
* libguile/ports.c (scm_c_make_port_with_encoding): Add SCM_OPN to mode
  bits, so that users don't have to.
  (scm_i_mode_bits_n):
* libguile/print.c (scm_simple_format)
* libguile/r6rs-ports.c (make_bytevector_input_port)
  (make_custom_binary_input_port, make_bytevector_output_port)
  (make_custom_binary_output_port, make_transcoded_port)
* libguile/strports.c (scm_object_to_string, scm_open_input_string)
  (scm_open_output_string, scm_c_read_string): Remove now-unneeded
  SCM_OPN mentions.
2016-05-14 12:42:17 +02:00
Andy Wingo
cd51ce81d0 Use heap-allocated port types instead of ptobnums
This removes a limitation on the number of port types, simplifies the
API, and removes a central point of coordination.

* libguile/ports-internal.h (struct scm_t_port_type): Rename from
  scm_t_ptob_descriptor, now that it's private.  Add GOOPS class
  fields.
  (struct scm_t_port): Rename from struct scm_port, especially
  considering that deprecated.h redefines scm_port using the
  preprocessor :(.
* libguile/ports.h: Add definitions of SCM_PORT and SCM_PORT_TYPE,
  though the scm_t_port and scm_t_port_type types are incomplete.
  (SCM_TC2PTOBNUM, SCM_PTOBNUM, SCM_PTOBNAME): Remove, as there are no
  more typecodes for port types.
  (scm_c_num_port_types, scm_c_port_type_ref, scm_c_port_type_add_x):
  Remove.
  (scm_make_port_type): Return a scm_t_port_type*.  All methods adapted
  to take a scm_t_port_type* instead of a ptobnum.
  (scm_c_make_port_with_encoding, scm_c_make_port): Take a port type
  pointer instead of a tag.
  (scm_new_port_table_entry): Remove; not useful.
* libguile/ports.c: Remove things related to the port kind table.  Adapt
  uses of SCM_PORT_DESCRIPTOR / scm_t_ptob_descriptor to use
  SCM_PORT_TYPE and scm_t_port_type.
* libguile/deprecated.c:
* libguile/deprecated.h:
* libguile/filesys.c:
* libguile/fports.c:
* libguile/fports.h:
* libguile/print.c:
* libguile/r6rs-ports.c:
* libguile/strports.c:
* libguile/strports.h:
* libguile/tags.h:
* libguile/vports.c:
* test-suite/standalone/test-scm-c-read.c: Adapt to change.
* libguile/goops.c (scm_class_of, make_port_classes)
  (scm_make_port_classes, create_port_classes): Adapt to store the
  classes in the ptob.
2016-05-13 18:31:29 +02:00
Andy Wingo
08574987d9 Remove scm_t_port_internal
* libguile/ports-internal.h (SCM_PORT): Rename from SCM_PTAB_ENTRY.
  (scm_t_port_internal, SCM_PORT_GET_INTERNAL): Remove.
  (SCM_FILENAME, SCM_SET_FILENAME, SCM_LINUM, SCM_COL): Adapt.
* libguile/ports.c:
* libguile/poll.c:
* libguile/ioext.c:
* libguile/fports.c:
* libguile/filesys.c:
* libguile/print.c:
* libguile/read.c:
* libguile/rw.c:
* libguile/strings.c: Adapt.
2016-05-13 11:34:52 +02:00
Andy Wingo
e5d2f4e566 Make scm_t_port private
* libguile/ports-internal.h (enum scm_port_encoding_mode): Remove unused
  enum.
  (scm_t_port_internal, scm_t_port): Make encoding and
  conversion_strategy private. Instead of scm_t_port_internal containing
  scm_t_port, now that all members are private, we can store the user's
  "stream" in a word in the port object itself and make the whole of
  scm_t_port private.  The next commit will remove scm_t_port_internal.
  (SCM_PTAB_ENTRY, SCM_PORT_DESCRIPTOR): Make private.
* libguile/ports.c (scm_c_make_port_with_encoding): Adapt to new port
  layout.
  (scm_port_print): Use SCM_PTAB_ENTRY when printing.
* libguile/ports.h: Remove scm_t_port definition.
* libguile/ioext.c (get_matching_port): Simplify.
* libguile/fports.c (scm_i_evict_port): Simplify.
2016-05-13 11:27:37 +02:00
Andy Wingo
9a9e0cceae Make port buffering fields private
* libguile/ports-internal.h (enum scm_port_buffer_field)
  (scm_t_port_internal): Make port buffering fields private.
* libguile/ports.h (scm_t_port): Adapt.
* libguile/filesys.c (set_element):
* libguile/ioext.c (scm_redirect_port):
* libguile/poll.c (scm_primitive_poll):
* libguile/ports.c:
* libguile/read.c (scm_i_scan_for_encoding):
* libguile/rw.c (scm_write_string_partial): Adapt users.
2016-05-13 10:58:19 +02:00
Andy Wingo
8af64975be Make file/line/column fields of ports private
* libguile/ports-internal.h (scm_t_port_internal): Move file_name,
  line_number, and column_number here.
  (SCM_FILENAME, SCM_SET_FILENAME, SCM_LINUM, SCM_COL, SCM_INCLINE):
  (SCM_ZEROCOL, SCM_INCCOL, SCM_DECCOL, SCM_TABCOL): Make internal.
* libguile/ports.c (scm_c_make_port_with_encoding)
  (scm_set_port_line_x, scm_set_port_column_x): Adapt to change.
2016-05-13 10:33:17 +02:00
Andy Wingo
209d50c7d8 Embed scm_t_port in scm_t_port_internal
* libguile/ports-internal.h (scm_t_port_internal)
* libguile/ports.h (scm_t_port): Embed scm_t_port in scm_t_port_internal
  so that we have just one allocation.
* libguile/ports-internal.h (SCM_PORT_GET_INTERNAL): Adapt.
* libguile/ports.c (scm_i_port_property, scm_i_set_port_property_x)
  (scm_c_make_port_with_encoding): Adapt.
2016-05-13 10:24:32 +02:00
Andy Wingo
fe7ceff969 Remove SCM backlink in port structure
* libguile/ports.h (scm_t_port): Remove port backlink.
* libguile/ports.c (scm_c_make_port_with_encoding, scm_fill_input)
  (scm_seek): Adapt.
2016-05-13 10:16:27 +02:00
Andy Wingo
6ff542ee71 Add random_access_p port type method
* doc/ref/api-io.texi (I/O Extensions): Update documentation on
  implementing port types.  Document get_natural_buffer_sizes.  Document
  the new random_access_p.
* libguile/fports.c (scm_i_fdes_to_port, fport_random_access_p):
  (scm_make_fptob): Instead of frobbing rw_random manually, implement a
  random_access_p function.
* libguile/ports.c (default_random_access_p)
  (scm_set_port_random_access_p): New functions.
  scm_make_port_type, scm_c_make_port_with_encoding): Arrange for
  random_access_p to work.
2016-05-13 10:05:23 +02:00
Andy Wingo
d1bb400c3f Beginnings of shunting ports-in-scheme off to a module
* libguile/ports.c (scm_specialize_port_encoding_x): Add some sanity
  checks.
  (scm_unget_bytes): Use scm_expand_port_read_buffer_x.
  (port_clear_stream_start_for_bom_read): Use
  scm_specialize_port_encoding_x.
  (scm_fill_input): Use scm_expand_port_read_buffer_x.
  (scm_expand_port_read_buffer_x): Rename from
  scm_set_port_read_buffer_x and actually expand the buffer.
* libguile/ports.h: Adapt to scm_expand_port_read_buffer_x change.

* module/ice-9/ports.scm: Remove ports-in-scheme stuff, and instead
  expose the ports internals via an auxiliary module.  This will let
  ports-in-scheme live in a module during Guile 2.2.
2016-05-13 09:09:42 +02:00
Andy Wingo
502e3a2213 Fix port-clear-stream-start-for-bom-read logic.
* libguile/ports.c (scm_port_clear_stream_start_for_bom_read): Fix
  logic.
2016-05-10 15:36:06 +02:00
Andy Wingo
8ee189980d Factor out iconv to port-decode-char
* libguile/ports.c (scm_port_decode_char): New helper, exported
  to (ice-9 ports).
  (peek_iconv_codepoint): Use scm_port_decode_char.
2016-05-10 12:45:56 +02:00
Andy Wingo
08c67dbef8 Simplify decoding error handling
* libguile/ports.c (peek_utf8_codepoint, peek_latin1_codepoint):
  (peek_iconv_codepoint, peek_codepoint): Refactor to push error
  handling to the leaves, where errors happen.  Just return
  the (possibly substituted) codepoint, without an error code; if
  there's really an error, we should raise it.
  (scm_getc, scm_peek_char): Adapt.
2016-05-10 12:09:30 +02:00
Andy Wingo
1953d29038 Decoding errors do not advance read pointer
* libguile/ports.c (scm_getc): If the port conversion strategy is
  'error, signal an error before advancing the read pointer.  This is a
  change from previous behavior; before, we advanced the read pointer
  under an understanding that that was what R6RS required.  But, that
  seems to be not the case.
* test-suite/tests/ports.test ("string ports"): Update decoding-error
  tests to assume that read-char with an error doesn't advance the read
  pointer.
* test-suite/tests/rdelim.test ("read-line"): Likewise.
2016-05-10 11:36:28 +02:00
Andy Wingo
83e5ccb02f Fix bug in trampoline_to_c_read
* libguile/ports.c (trampoline_to_c_read): Fix bug comparing SCM
  values.
2016-05-10 11:08:41 +02:00
Andy Wingo
13f2128587 Fix port-clear-stream-start-for-bom-read bug
* libguile/ports.c (scm_port_clear_stream_start_for_bom_read): Fix to
  return SCM_BOOL_F instead of 0.
2016-05-07 12:40:46 +02:00
Andy Wingo
6d15a71e8f Port to Scheme of new BOM handling
* libguile/ports.c (scm_specialize_port_encoding_x)
  (scm_port_clear_stream_start_for_bom_read): New functions exported
  to (ice-9 ports).
* module/ice-9/ports.scm (clear-stream-start-for-bom-read):
  (fill-input, peek-char-and-len): Rework to handle BOM in fill-input
  instead of once per peek-char.
2016-05-05 22:54:58 +02:00
Andy Wingo
86267af8b3 Handle BOM around fill/flush instead of peek/put
* libguile/print.c (display_string_using_iconv): Remove BOM handling;
  this is now handled by scm_lfwrite.
* libguile/ports.c (open_iconv_descriptors): Refactor to take encoding
  as a symbol.
  (prepare_iconv_descriptors): New helper.
  (scm_i_port_iconv_descriptors): Remove scm_t_port_rw_active argument,
  and don't sniff UTF-16/UTF-32 byte orders here.  Instead BOM handlers
  will call prepare_iconv_descriptors.
  (scm_c_read_bytes): Call new port_clear_stream_start_for_bom_read
  helper.
  (port_maybe_consume_initial_byte_order_mark)
  (scm_port_maybe_consume_initial_byte_order_mark): Remove.  Leaves
  Scheme %peek-char broken but it's unused currently so that's OK.
  (peek_iconv_codepoint): Fetch iconv descriptors after doing fill-input
  because it's fill-input that will sniff the BOM.
  (peek_codepoint): Instead of handling BOM at every character, handle
  in fill-input instead.
  (maybe_consume_bom, port_clear_stream_start_for_bom_read)
  (port_clear_stream_start_for_bom_write): New helpers.
  (scm_fill_input): Slurp a BOM if needed.
  (scm_i_write): Clear the start-of-stream-for-bom-write flag.
  (scm_lfwrite): Write a BOM if needed.
2016-05-05 13:00:19 +02:00
Andy Wingo
36e32138f8 Port refactors to help Scheme peek-char
* libguile/ports.h (scm_sys_port_encoding, scm_sys_set_port_encoding):
  New functions, to expose port encodings as symbols directly to (ice-9
  ports).
  (scm_port_maybe_consume_initial_byte_order_mark): New function.
* libguile/ports.c (scm_port_encoding): Dispatch to %port-encoding.
  (scm_set_port_encoding_x): Dispatch to %set-port-encoding!.
  (port_maybe_consume_initial_byte_order_mark): New helper, factored out
  of peek_codepoint.
  (scm_port_maybe_consume_initial_byte_order_mark, peek_codepoint): Call
  port_maybe_consume_initial_byte_order_mark.
* module/ice-9/ports.scm (port-encoding): Implement in Scheme.
2016-05-04 11:47:42 +02:00
Andy Wingo
383df7976f Port conversion strategies internally are symbols
* libguile/ports.h (scm_t_port): Represent the conversion strategy as a
  symbol, to make things easier for Scheme.  Rename to
  "conversion_strategy".
  (scm_c_make_port_with_encoding): Change to take encoding and
  conversion_strategy arguments as symbols.
  (scm_i_string_failed_conversion_handler): New internal helper, to turn
  a symbol to a scm_t_string_failed_conversion_handler.
  (scm_i_default_port_encoding): Return the default port encoding as a
  symbol.
  (scm_i_default_port_conversion_strategy)
  (scm_i_set_default_port_conversion_strategy): Rename from
  scm_i_default_port_conversion_handler et al.  Take and return Scheme
  symbols.
* libguile/foreign.c (scm_string_to_pointer, scm_pointer_to_string): Use
  scm_i_default_string_failed_conversion_handler instead of
  scm_i_default_port_conversion_handler.
* libguile/print.c (PORT_CONVERSION_HANDLER): Update definition.
  (print_normal_symbol): Use PORT_CONVERSION_HANDLER.
* libguile/r6rs-ports.c (make_bytevector_input_port):
  (make_custom_binary_input_port, make_bytevector_output_port): Adapt to
  changes in scm_c_make_port_with_encoding.
* libguile/strings.h:
* libguile/strings.c (scm_i_default_string_failed_conversion_handler):
  New helper.
  (scm_from_locale_stringn, scm_from_port_stringn):
  (scm_to_locale_stringn, scm_to_port_stringn): Adapt to interface
  changes.
* libguile/strports.c (scm_mkstrport): Adapt to
  scm_c_make_port_with_encoding change.
* libguile/ports.c (scm_c_make_port): Adapt to
  scm_c_make_port_with_encoding change.
  (ascii_toupper, encoding_matches, canonicalize_encoding): Move down in
  the file.
  (peek_codepoint, get_codepoint, scm_ungetc): Adapt to port conversion
  strategy change.  Remove duplicate case in get_codepoint.
  (scm_init_ports): Move symbol initializations to the same place.
2016-05-04 10:41:07 +02:00
Andy Wingo
d8711b9759 Port encoding internally represented as symbol
* libguile/ports-internal.h (scm_t_port_internal): Remove encoding_mode
  member.
* libguile/ports.h (scm_t_port): "encoding" member is now a SCM symbol.
* libguile/ports.c (scm_init_ports): Define symbols for the encodings
  that we handle explicitly.
  (encoding_matches): Adapt to check against an encoding as a symbol.
  (canonicalize_encoding): Return an encoding as a symbol.
  (scm_c_make_port_with_encoding, scm_i_set_default_port_encoding)
  (decide_utf16_encoding, decide_utf32_encoding)
  (scm_i_port_iconv_descriptors, scm_i_set_port_encoding_x)
  (scm_port_encoding, peek_codepoint, scm_ungetc): Adapt to encoding
  change.

* libguile/print.c (display_string_using_iconv, display_string):
* libguile/read.c (scm_read_character):
* libguile/strings.c (scm_from_port_stringn, scm_to_port_stringn): Adapt
  to port encoding change.
2016-05-03 10:52:54 +02:00