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

9310 commits

Author SHA1 Message Date
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
f5b9a53bd0 Add integer->char and char->integer opcodes
* libguile/vm-engine.c (integer_to_char, char_to_integer): New opcodes.
* libguile/vm.c (vm_error_not_a_char): New error case.
* module/language/cps/compile-bytecode.scm (compile-function):
* module/language/cps/slot-allocation.scm (compute-var-representations):
* module/language/cps/types.scm:
* module/language/tree-il/compile-cps.scm (convert):
* doc/ref/vm.texi (Inlined Scheme Instructions):
* module/system/vm/assembler.scm: Add support for new opcodes.
2016-05-04 12:36:41 +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
Andy Wingo
1309ab8093 Char readers peek into read buffer
* libguile/ports.c (scm_i_set_pending_eof): Remove now-unused helper.
  (peek_utf8_codepoint, peek_latin1_codepoint, peek_iconv_codepoint):
  (peek_codepoint): Refactor the fundamental character readers in Guile
  to peek into the read buffer instead of reading then unreading.  This
  will allow Scheme to use the port buffer to convert, when we port this
  to Scheme.
  (get_codepoint): Use peek_codepoint.
  (scm_getc): Adapt.
  (scm_peek_char): Use peek_codepoint.
2016-05-01 16:58:57 +02:00
Andy Wingo
56c48d14ac scm_fill_input can guarantee a minimum fill amount
* libguile/ports.h (scm_fill_input): Add "minimum_size" argument.  Adapt
  all callers to pass 0 as this argument.
* libguile/ports.c (scm_i_read): Inline into scm_fill_input.
  (scm_fill_input): "minimum_size" argument ensures that there are a
  certain number of bytes available, or EOF.  Instead of shrinking the
  read buffer, only fill by the read_buffering amount, or the
  minimum_size, whichever is larger.
* libguile/r6rs-ports.c:
* libguile/read.c: Adapt scm_fill_input callers.
2016-05-01 14:29:17 +02:00
Andy Wingo
6a752bcf2a peek-byte in Scheme
* libguile/ports.c (trampoline_to_c_read, trampoline_to_c_write): Since
  C might assume that the indices are within bounds of the bytevector,
  verify them more here.
  (scm_port_random_access_p, scm_port_read_buffering)
  (scm_set_port_read_buffer, scm_port_read, scm_port_write): New helpers
  exposed to (ice-9 ports).
  (scm_port_read_buffer, scm_port_write_buffer): Don't flush or validate
  port mode; we do that in Scheme.
* module/ice-9/ports.scm: Implement enough of port machinery to
  implement peek-byte in Scheme.  Not yet exported.
2016-04-30 14:46:45 +02:00
Andy Wingo
300c85b0f0 Tweak port initialization order
* libguile/init.c (scm_i_init_guile): Initialize ports before
  strports/fports, so that we have initialized the read/write
  trampolines before making port types.
2016-04-30 14:45:44 +02:00
Andy Wingo
555c934726 Refactor way the-eof-object is defined
* libguile/ports.c (scm_init_ice_9_ports): Define the-eof-object here.
  Update a comment.
* module/ice-9/ports.scm: Use the-eof-object definition from C.
2016-04-30 14:44:20 +02:00
Andy Wingo
8bad621fec Add SCM port read/write functions
* libguile/ports.h (scm_t_ptob_descriptor): Add "scm_read" and
  "scm_write" members, for calling from Scheme.
  (scm_set_port_scm_read, scm_set_port_scm_write): New procedures.
* libguile/ports.c (trampoline_to_c_read_subr)
  (trampoline_to_c_write_subr): New static variables.
* libguile/ports.c (scm_make_port_type): Initialize scm_read and
  scm_write members to trampoline to C.
  (trampoline_to_c_read, trampoline_to_scm_read)
  (trampoline_to_c_write, trampoline_to_scm_write): New helpers.
  (scm_set_port_scm_read, scm_set_port_scm_write): New functions.
  (default_buffer_size): Move definition down.
  (scm_i_read_bytes, scm_i_write_bytes): Use new names for read and
  write procedures.
  (scm_init_ports): Initialize trampolines.
2016-04-30 11:59:33 +02:00
Andy Wingo
2b47043052 Remove port locks
* libguile/ports.h (scm_t_port): Remove lock field.
  (scm_dynwind_lock_port, scm_c_lock_port, scm_c_try_lock_port):
  Remove.
* libguile/ports.c (scm_i_port_property, scm_i_set_port_property_x):
  Remove locking.
* libguile/ports.c (scm_c_make_port_with_encoding): Remove lock.
  (scm_i_read_bytes, scm_i_read, scm_i_write_bytes, scm_i_write): Remove
  "_unlocked" from names and adapt callers.
2016-04-28 08:34:08 +02:00
Andy Wingo
8b46a4af44 Optimize peek-char
* libguile/ports.c (scm_peek_char): Optimize.  A loop calling peek-char
  on a buffered string port 10e6 times goes down from 50ns/iteration to
  32ns/iteration.
2016-04-28 08:16:43 +02:00
Andy Wingo
ee4854a315 Remove port locking around write, display
* libguile/print.c (scm_write, scm_display):
* libguile/read.c (set_port_read_option): Remove port locking.  Reading
  and writing to the same port from multiple threads just must not
  crash; it doesn't have to make sense.
2016-04-28 08:16:42 +02:00
Andy Wingo
15d5304723 scm_lfwrite, not scm_lfwrite_unlocked
* libguile/ports.h (scm_lfwrite_unlocked): Remove.
* libguile/ports.c (scm_lfwrite): Rename from scm_lfwrite_unlocked.
* libguile/numbers.c:
* libguile/print.c: Adapt to call scm_lfwrite.
2016-04-26 23:17:22 +02:00
Andy Wingo
d0b9d3b04d Remove scm_c_write_unlocked
* libguile/ports.h (scm_c_write_bytes_unlocked): Remove.
* libguile/ports.c (scm_c_write_bytes): Rename from
  scm_c_write_bytes_unlocked, make public, and return void.
  (scm_c_write): Rename from scm_c_write_unlocked.  Remove locked
  variant.
  (scm_lfwrite_unlocked): Call scm_c_write.
* libguile/rw.c (scm_write_string_partial): Call scm_c_write.
2016-04-26 23:13:32 +02:00
Andy Wingo
105e36543f Remove scm_puts_unlocked.
* libguile/ports.h (scm_puts_unlocked): Remove.
* libguile/ports.c (scm_puts): Replace implementation with
  scm_puts_unlocked's implementation.
* libguile/arbiters.c:
* libguile/backtrace.c:
* libguile/bitvectors.c:
* libguile/continuations.c:
* libguile/deprecation.c:
* libguile/dynl.c:
* libguile/eval.c:
* libguile/filesys.c:
* libguile/fluids.c:
* libguile/foreign.c:
* libguile/fports.c:
* libguile/frames.c:
* libguile/guardians.c:
* libguile/hashtab.c:
* libguile/hooks.c:
* libguile/load.c:
* libguile/macros.c:
* libguile/mallocs.c:
* libguile/print.c:
* libguile/programs.c:
* libguile/promises.c:
* libguile/smob.c:
* libguile/srcprop.c:
* libguile/srfi-14.c:
* libguile/stackchk.c:
* libguile/struct.c:
* libguile/threads.c:
* libguile/throw.c:
* libguile/values.c:
* libguile/variable.c:
* libguile/vm.c:
* libguile/weak-set.c:
* libguile/weak-table.c: Use scm_puts instead of scm_puts_unlocked.
2016-04-26 23:07:28 +02:00
Andy Wingo
206b3f6e03 Remove scm_putc_unlocked.
* libguile/ports.h (scm_putc_unlocked): Remove.
* libguile/ports.c (scm_putc): Replace implementation with
  scm_putc_unlocked's implementation.
  (scm_port_print): Use scm_putc.
* libguile/arbiters.c:
* libguile/arrays.c:
* libguile/bitvectors.c:
* libguile/bytevectors.c:
* libguile/continuations.c:
* libguile/dynl.c:
* libguile/eval.c:
* libguile/filesys.c:
* libguile/fluids.c:
* libguile/foreign.c:
* libguile/fports.c:
* libguile/frames.c:
* libguile/hashtab.c:
* libguile/hooks.c:
* libguile/macros.c:
* libguile/mallocs.c:
* libguile/print.c:
* libguile/programs.c:
* libguile/promises.c:
* libguile/r6rs-ports.c:
* libguile/smob.c:
* libguile/srcprop.c:
* libguile/struct.c:
* libguile/variable.c:
* libguile/weak-set.c:
* libguile/weak-table.c: Use scm_putc instead of scm_putc_unlocked.
2016-04-26 23:01:14 +02:00
Andy Wingo
796676028b Remove scm_fill_input_unlocked
* libguile/ports.h (scm_fill_input_unlocked): Remove.
* libguile/ports.c (scm_fill_input): Rename from
  scm_fill_input_unlocked.  Adapt callers.
* libguile/r6rs-ports.c (scm_get_bytevector_some): Adapt.
* libguile/read.c (scm_i_scan_for_encoding): Adapt.
2016-04-26 22:37:04 +02:00
Andy Wingo
abf90c4e72 Remove locking in scm_end_input
* libguile/ports.c (scm_end_input): Sadly, we can't naively lock around
  the scm_port_buffer_take, as it might throw.  Will revisit in the
  future.
2016-04-26 22:11:41 +02:00
Andy Wingo
122c8e6b37 scm_ungetc, scm_ungets instead of _unlocked variants
* libguile/ports.h (scm_ungetc_unlocked, scm_ungets_unlocked): Remove;
  replace with scm_ungetc, scm_ungets.
* libguile/ports.c (scm_ungetc, scm_ungets, scm_unread_char)
  (scm_unread_string): Adapt.
* libguile/rdelim.c (scm_read_delimited_x): Use scm_ungetc.
* libguile/read.c: Unread characers with scm_ungetc, not
  scm_ungetc_unlocked.
2016-04-23 22:20:18 +02:00
Andy Wingo
21650f8d52 Remove scm_unget_{byte,bytes}_unlocked
* libguile/ports.h (scm_unget_bytes_unlocked, scm_unget_byte_unlocked):
  Remove.
* libguile/ports.c (looking_at_bytes): Use scm_unget_bytes instead of
  scm_i_unget_bytes_unlocked
  (scm_unget_bytes): Rename from scm_i_unget_bytes_unlocked.  Remove
  other implementations of this function.
  (scm_unget_byte): Likewise.
  (scm_ungetc_unlocked, scm_peek_char): Use scm_unget_byte.
* libguile/read.c (read_token): Use scm_unget_byte.
2016-04-23 21:53:54 +02:00
Andy Wingo
cd83872df8 Replace scm_getc with scm_getc_unlocked
* libguile/ports.h (scm_getc_unlocked): Remove, or rather rename to
  scm_getc.  This probably introduces some thread-related bugs but we'll
  fix them in a different way.
* libguile/ports.c (scm_getc): Rename from scm_getc_unlocked, replacing
  the locky implementation.
  (scm_read_char): Use scm_getc.
* libguile/r6rs-ports.c (scm_get_string_n_x): Use scm_getc.
* libguile/rdelim.c (scm_read_delimited_x, scm_read_line): Use
  scm_getc.
* libguile/read.c: Use scm_getc.
2016-04-23 21:53:54 +02:00
Andy Wingo
9632b24c4d Remove scm_c_read_bytes_unlocked
* libguile/ports.c (scm_c_read_bytes_unlocked): Remove internal
  function.
2016-04-23 21:53:54 +02:00
Andy Wingo
99899b7c9c Remove scm_flush_unlocked / scm_end_input_unlocked
* libguile/ports.h (scm_flush_unlocked, scm_end_input_unlocked):
  Remove.
* libguile/ports.c (scm_c_read_bytes_unlocked):
  (scm_i_unget_bytes_unlocked, scm_setvbuf, scm_force_output)
  (scm_fill_input_unlocked, scm_c_write_bytes_unlocked)
  (scm_c_write_unlocked, scm_lfwrite_unlocked, scm_seek)
  (scm_truncate_file, flush_output_port): Call scm_flush / scm_end_input
  instead of the _unlocked variants.
  (scm_end_input): Lock while discarding the input buffer but not while
  calling out to the seek function.
* libguile/filesys.c (scm_fsync):
* libguile/ioext.c (scm_redirect_port):
* libguile/read.c (scm_i_scan_for_encoding):
* libguile/rw.c (scm_write_string_partial): Use scm_flush, not
  scm_flush_unlocked.
2016-04-23 15:21:43 +02:00
Andy Wingo
69a1b83f31 Remove port rw_active field
* libguile/ports.h (scm_t_port_rw_active): Move type definition to
  ports-internal.h.
  (scm_t_port): Remove rw_active field.  It's sufficient to check the
  port buffer cursors.
* libguile/read.c (scm_i_scan_for_encoding): Just call
  scm_flush_unlocked; it's idempotent.
* libguile/ports.c (scm_c_make_port_with_encoding): Remove rw_active
  field.
  (scm_c_read_bytes_unlocked, scm_c_read, scm_i_unget_bytes_unlocked)
  (scm_end_input_unlocked, scm_flush_unlocked, scm_fill_input_unlocked)
  (scm_port_write_buffer, scm_port_read_buffer)
  (scm_c_write_bytes_unlocked, scm_c_write_unlocked, scm_seek): Remove
  management of rw_active field.
2016-04-22 21:08:30 +02:00
Andy Wingo
4934b69ddf scm_c_read instead of scm_c_read_unlock
* libguile/ports.h (scm_c_read_unlocked): Remove.
* libguile/ports.c (scm_c_read): Rename from scm_c_read_unlocked.
  Remove old scm_c_read.  Lock around access to the rw_active flag, and
  call scm_flush instead of scm_flush_unlocked, and scm_fill_input
  instead of scm_fill_input_unlocked.
* libguile/read.c (scm_i_scan_for_encoding): Use scm_c_read instead of
  the _unlocked function.
2016-04-22 20:42:24 +02:00
Andy Wingo
fb577b59af Refactor to internal get/peek-byte functions
* libguile/ports.h (scm_get_byte_or_eof_unlocked)
  (scm_peek_byte_or_eof_unlocked): Remove inline functions.  The
  important uses are in ports.c anyway and we will use a static function
  there.
  (scm_slow_get_byte_or_eof_unlocked)
  (scm_slow_peek_byte_or_eof_unlocked): Remove declarations without
  definitions.
* libguile/ports.c (looking_at_bytes): Use scm_peek_byte_or_eof instead
  of the _unlocked variant.
  (get_byte_or_eof, peek_byte_or_eof): New static functions.
  (scm_get_byte_or_eof, scm_peek_byte_or_eof): Don't lock: the port
  buffer mechanism means that we won't crash.  More comments to come.
  (get_utf8_codepoint, get_latin1_codepoint, get_iconv_codepoint): Use
  new static functions.
* libguile/read.c (read_token, scm_read_semicolon_comment): Use
  scm_get_byte_or_eof, not scm_get_byte_or_eof_unlocked.
2016-04-22 17:12:58 +02:00
Andy Wingo
3e951f7dfc Refactor thread safety for %port-property
* libguile/ports.c (scm_i_port_property, scm_i_set_port_property_x):
  Knowing that the critical section can't throw, use serial lock
  discipline.
2016-04-22 17:05:35 +02:00
Andy Wingo
5a342f61c4 Port buffers are Scheme values
* libguile/ports-internal.h (scm_port_buffer_bytevector)
  (scm_port_buffer_cur, scm_port_buffer_set_cur)
  (scm_port_buffer_end, scm_port_buffer_set_end)
  (scm_port_buffer_has_eof_p, scm_port_buffer_set_has_eof_p): New
  helpers.
* libguile/ports-internal.h (scm_port_buffer_size)
  (scm_port_buffer_reset, scm_port_buffer_reset_end)
  (scm_port_buffer_can_take, scm_port_buffer_can_put)
  (scm_port_buffer_can_putback, scm_port_buffer_did_take)
  (scm_port_buffer_did_put, scm_port_buffer_take_pointer)
  (scm_port_buffer_put_pointer, scm_port_buffer_take)
  (scm_port_buffer_put, scm_port_buffer_putback): Adapt to treat port
  buffers as SCM values and use helpers to access them.
* libguile/ports.c (scm_i_clear_pending_eof, scm_i_set_pending_eof)
  (scm_c_make_port_buffer, scm_i_read_unlocked)
  (scm_c_read_bytes_unlocked, scm_i_unget_bytes_unlocked)
  (scm_setvbuf, scm_fill_input, scm_take_from_input_buffers)
  (scm_drain_input, scm_end_input_unlocked, scm_flush_unlocked)
  (scm_fill_input_unlocked, scm_i_write_unlocked)
  (scm_c_write_bytes_unlocked, scm_c_write_unlocked)
  (scm_char_ready_p): Adapt to treat port buffers as SCM values and use
  helpers to access them.
  (scm_port_read_buffer, scm_port_write_buffer): New functions,
  allowing (ice-9 ports) to access port buffers.
* libguile/ports.h: Update comments on port buffers.  Replace
  scm_t_port_buffer structure with a Scheme vector whose fields are
  enumerated by "enum scm_port_buffer_field".
  (scm_get_byte_or_eof_unlocked, scm_peek_byte_or_eof_unlocked): Adapt
  these implementations to port buffer representation change.
* libguile/r6rs-ports.c (scm_get_bytevector_some):
* libguile/read.c (scm_i_scan_for_encoding):
* libguile/rw.c (scm_write_string_partial): Port buffers are Scheme
  objects.
2016-04-20 09:22:20 +02:00
Andy Wingo
bb6edc5a35 peek-u8 correctness and speed refactor
* libguile/ports-internal.h (scm_port_buffer_size): Verify that the
  bytevector field is a bytevector, in anticipation of Schemification.
  (scm_port_buffer_can_take, scm_port_buffer_can_put)
  (scm_port_buffer_can_putback): Enforce invariants on cur and end
  here.
  (scm_port_buffer_did_take, scm_port_buffer_did_put): Relax to not call
  other functions.
* libguile/ports.h (scm_get_byte_or_eof_unlocked)
  (scm_peek_byte_or_eof_unlocked): Refactor to call no functions on the
  fast path.
2016-04-19 22:58:33 +02:00
Andy Wingo
ffb4347d53 Port buffer cur/next pointers are Scheme values
* libguile/ports.h (scm_t_port_buffer): Change "cur" and "end" members
  to be SCM values, in preparation for changing port buffers to be
  Scheme vectors.
  (scm_get_byte_or_eof_unlocked, scm_peek_byte_or_eof_unlocked): Adapt.
* libguile/ports.c (scm_c_make_port_buffer): Initialize cur and end
  members.
  (looking_at_bytes): Use helper instead of incrementing cur.
  (scm_i_read_unlocked): Adapt to end type change.
  (CONSUME_PEEKED_BYTE): Use helper instead of incrementing cur.
  (scm_i_unget_bytes_unlocked): Use helper instead of comparing cur.
  (scm_i_write_unlocked): Fix for changing end/cur types.
* libguile/read.c (scm_i_scan_for_encoding): Use helpers instead of
  addressing cursors directly.
* libguile/rw.c (scm_write_string_partial): Likewise.
* libguile/ports-internal.h (scm_port_buffer_reset):
  (scm_port_buffer_reset_end, scm_port_buffer_can_take):
  (scm_port_buffer_can_put, scm_port_buffer_can_putback):
  (scm_port_buffer_did_take, scm_port_buffer_did_put):
  (scm_port_buffer_take_pointer, scm_port_buffer_put_pointer):
  (scm_port_buffer_putback): Adapt to data types.
2016-04-19 20:02:05 +02:00
Andy Wingo
10dc6d043e Remove "buf" field from port buffers
* libguile/ports-internal.h (scm_port_buffer_reset_end): New helper.
  (scm_port_buffer_putback): New helper.
* libguile/ports.h (scm_t_port_buffer): Remove "buf" field.
  (scm_get_byte_or_eof_unlocked, scm_peek_byte_or_eof_unlocked): Adapt.
* libguile/ports.c (scm_c_make_port_buffer): No more "buf" field.
  (scm_i_unget_bytes_unlocked): Use helper.
* libguile/read.c (scm_i_scan_for_encoding): No more "buf" field.
2016-04-18 00:19:24 +02:00
Andy Wingo
b869344a4f Remove size field from port buffers
* libguile/ports.h (scm_t_port_buffer): Remove size field.  Instead use
  bytevector size.
* libguile/ports-internal.h (scm_port_buffer_size)
  (scm_port_buffer_reset)
  (scm_port_buffer_can_take, scm_port_buffer_can_put)
  (scm_port_buffer_did_take, scm_port_buffer_did_put)
  (scm_port_buffer_take_pointer, scm_port_buffer_put_pointer)
  (scm_port_buffer_take, scm_port_buffer_put): New helpers.
* libguile/filesys.c (set_element): Use new helpers.
* libguile/poll.c (scm_primitive_poll): Use new helpers.
* libguile/ports.c (scm_c_make_port_buffer): No more "size" field.
  (scm_i_read_unlocked, scm_c_read_bytes_unlocked)
  (scm_c_read_unlocked, scm_i_unget_bytes_unlocked)
  (scm_unget_bytes, scm_setvbuf, scm_take_from_input_buffers)
  (scm_drain_input, scm_end_input_unlocked, scm_flush_unlocked)
  (scm_fill_input_unlocked, scm_i_write_unlocked)
  (scm_c_write_bytes_unlocked, scm_c_write_unlocked)
  (scm_char_ready_p): Use new helpers.
* libguile/r6rs-ports.c (scm_get_bytevector_some): Use new helpers.
* libguile/rw.c (scm_write_string_partial): Use new helpers.
2016-04-17 19:38:44 +02:00
Andy Wingo
f62974000f Port buffer has-eof? field is SCM value
* libguile/ports.h (scm_t_port_buffer): Rename has_eof member to
  has_eof_p, and be a Scheme value, in anticipation of moving the port
  buffers to be Scheme objects.
2016-04-17 15:42:13 +02:00
Andy Wingo
2214fff524 Remove unrelated scm_t_port_buffer use in vports
* libguile/vports.c (struct soft_port): Inline the encoding buffer so as
  to not use scm_t_port_buffer, in anticipation of changing the port
  buffer representations.  Adapt users.
2016-04-17 14:39:51 +02:00
Andy Wingo
44b3342c4d Load port bindings in separate (ice-9 ports) module
* module/ice-9/ports.scm: New file.
* am/bootstrap.am (SOURCES): Add ice-9/ports.scm.
* libguile/fports.c (scm_init_ice_9_fports): New function.
  (scm_init_fports): Arrange for scm_init_ice_9_fports to be called via
  load-extension, and load snarfed things there.  Move open-file
  definition early, to allow ports to bootstrap.
* libguile/ioext.c (scm_init_ice_9_ioext): New function.
  (scm_init_ioext): Similarly, register scm_init_ice_9_ioext as an
  extension.
* libguile/ports.c (scm_set_current_input_port)
  (scm_set_current_output_port, scm_set_current_error_port): Don't
  define Scheme bindings; do that in Scheme.
* libguile/ports.c (scm_i_set_default_port_encoding):
  (scm_i_default_port_encoding, scm_i_default_port_conversion_handler):
  (scm_i_set_default_port_conversion_handler): Since we now init
  encoding early, remove the "init" flags on these encoding/strategy
  vars.
  (scm_init_ice_9_ports): New function.
  (scm_init_ports): Register scm_init_ice_9_ports extension, and define
  some bindings needed by the bootstrap.
* module/Makefile.am (SOURCES): Add ice-9/ports.scm.
* module/ice-9/boot-9.scm: Remove code that's not on the boot path,
  moving it to ice-9/ports.scm.  At the end, load (ice-9 ports).
* module/ice-9/psyntax.scm (include): Use close-port instead of
  close-input-port.
* module/ice-9/psyntax-pp.scm (include): Regenerate.
2016-04-15 14:07:02 +02:00
Andy Wingo
cf80502c0a Fix scm_init_struct dependency on port conversion handlers
* libguile/struct.c (scm_init_struct): Use scm_from_latin1_string to
  avoid locale-dependency for what is really a latin1 string.  Also
  avoids an early dependency on the default port conversion handler,
  though I wonder if using port conversion handlers in strings is the
  right thing.
2016-04-14 11:06:40 +02:00
Andy Wingo
a9cf9f424f Allow port "write" functions to only write a chunk
* libguile/ports.c (scm_i_write_bytes_unlocked): Allow incomplete
  writes from the implementation.
  (scm_c_write_bytes_unlocked): Use scm_i_write_bytes_unlocked helper to
  call the write function.
* libguile/r6rs-ports.c (custom_binary_output_port_write): Don't loop;
  core Guile will do that.
2016-04-12 16:45:10 +02:00
Andy Wingo
f7027a8b88 Port read/write functions take bytevectors
This will allow better Scheme integration for ports.

* libguile/ports.h (scm_t_port_buffer): Change "holder" member to be a
  bytevector defined to have "buf" as its starting point.
  (scm_t_ptob_descriptor): Change read and write functions to take
  bytevectors as arguments and to return the number of octets read or
  written.
  (scm_make_port_type): Adapt accordingly.
  (scm_c_read_bytes, scm_c_write_bytes): New functions that take
  bytevectors.
* libguile/ports.c (scm_make_port_type): Adapt to read/write function
  prototype change.
  (scm_c_make_port_buffer): Arrange to populate the "bytevector" field.
  (scm_i_read_bytes_unlocked): New function.
  (scm_i_read_unlocked): Use scm_i_read_bytes_unlocked.
  (scm_c_read_bytes_unlocked): New function.
  (scm_c_read_unlocked): Update comment, and always go through the
  buffer.
  (scm_c_read_bytes): New function.
  (scm_flush_unlocked): Use scm_i_write_unlocked instead of the port's
  write function.
  (scm_i_write_bytes_unlocked): New function.
  (scm_i_write_unlocked): Use scm_i_write_bytes_unlocked.
  (scm_c_write_bytes_unlocked): New function.
  (scm_c_write_unlocked): Always write through the buffer.
  (scm_c_write_bytes): New function.
  (scm_truncate_file): Remove unused variable.
  (void_port_read, void_port_write): Adapt to read/write prototype
  change.
* libguile/fports.c (fport_read, fport_write):
* libguile/r6rs-ports.c (bytevector_input_port_read)
  (custom_binary_input_port_read, bytevector_output_port_write)
  (custom_binary_output_port_write, transcoded_port_write)
  (transcoded_port_read): Adapt to read/write prototype
  change.
  (scm_get_bytevector_n, scm_get_bytevector_n_x)
  (scm_get_bytevector_all): Use scm_c_read_bytes.
  (scm_put_bytevector): Use scm_c_write_bytes.
* libguile/strports.c (string_port_read, string_port_write):
* libguile/vports.c (soft_port_write, soft_port_read): Adapt to
  read/write prototype change.
* test-suite/standalone/test-scm-c-read.c (custom_port_read): Fix for
  read API change.
2016-04-11 22:23:47 +02:00
Andy Wingo
8399e7af51 Generic port facility provides buffering uniformly
* libguile/ports.h (struct scm_t_port_buffer): New data type.
  (struct scm_t_port): Refactor to use port buffers instead of
  implementation-managed read and write pointers.  Add "read_buffering"
  member.
  (SCM_INITIAL_PUTBACK_BUF_SIZE, SCM_READ_BUFFER_EMPTY_P): Remove.
  (scm_t_ptob_descriptor): Rename "fill_input" function to "read", and
  take a port buffer, returning void.  Likewise "write" takes a port
  buffer and returns void.  Remove "end_input"; instead if there is
  buffered input and rw_random is true, then there must be a seek
  function, so just seek back if needed.  Remove "flush"; instead all
  calls to the "write" function implicitly include a "flush", since the
  buffering happens in the generic port code now.  Remove "setvbuf", but
  add "get_natural_buffer_sizes"; instead the generic port code can
  buffer any port.
  (scm_make_port_type): Adapt to read and write prototype changes.
  (scm_set_port_flush, scm_set_port_end_input, scm_set_port_setvbuf):
  Remove.
  (scm_slow_get_byte_or_eof_unlocked)
  (scm_slow_get_peek_or_eof_unlocked): Remove; the slow path is to call
  scm_fill_input.
  (scm_set_port_get_natural_buffer_sizes): New function.
  (scm_c_make_port_buffer): New internal function.
  (scm_port_non_buffer): Remove.  This was a function for
  implementations that is no longer needed.  Instead open with BUF0 or
  use (setvbuf port 'none).
  (scm_fill_input, scm_fill_input_unlocked): Return the filled port
  buffer.
  (scm_get_byte_or_eof_unlocked, scm_peek_byte_or_eof_unlocked): Adapt
  to changes in buffering and EOF management.
* libguile/ports.c: Adapt to port interface changes.
  (initialize_port_buffers): New function, using the port mode flags to
  set up appropriate initial buffering for all ports.
  (scm_c_make_port_with_encoding): Create port buffers here instead of
  delegating to implementations.
  (scm_close_port): Flush the port if needed instead of delegating to
  the implementation.
* libguile/filesys.c (set_element): Adapt to buffering changes.
* libguile/fports.c (fport_get_natural_buffer_sizes): New function,
  replacing scm_fport_buffer_add.
  (fport_write, fport_read): Update to let the generic ports code do the
  buffering.
  (fport_flush, fport_end_input): Remove.
  (fport_close): Don't flush in a dynwind; that's the core ports' job.
  (scm_make_fptob): Adapt.
* libguile/ioext.c (scm_redirect_port): Adapt to buffering changes.
* libguile/poll.c (scm_primitive_poll): Adapt to buffering changes.
* libguile/ports-internal.h (struct scm_port_internal): Remove
  pending_eof flag; this is now set on the read buffer.
* libguile/r6rs-ports.c (struct bytevector_input_port): New type.  The
  new buffering arrangement means that there's now an intermediate
  buffer between the bytevector and the user of the port; this could
  lead to a perf degradation, but on the other hand there are some other
  speedups enabled by the buffering refactor, so probably the memcpy
  cost is dwarfed by the cost of the other parts of the ports
  machinery.
  (make_bytevector_input_port, bytevector_input_port_read):
  (bytevector_input_port_seek, initialize_bytevector_input_ports): Adapt
  to new buffering arrangement.
  (struct custom_binary_port): Remove read buffer, as Guile handles that
  now.
  (custom_binary_input_port_setvbuf): Remove; now handled by Guile.
  (make_custom_binary_input_port, custom_binary_input_port_read)
  (initialize_custom_binary_input_ports): Adapt.
  (scm_get_bytevector_some): Adapt to new EOF management.
  (scm_t_bytevector_output_port_buffer): Hold on to the underlying port,
  so we can flush it if it's open.
  (make_bytevector_output_port, bytevector_output_port_write):
  (bytevector_output_port_seek): Adapt.
  (bytevector_output_port_procedure): Flush the port as appropriate, so
  that we get all the bytes.
  (make_custom_binary_output_port, custom_binary_output_port_write):
  Adapt.
  (make_transcoded_port): Don't muck with buffering.
  (transcoded_port_write): Simply forward the write to the underlying
  port.
  (transcoded_port_read): Likewise.
  (transcoded_port_close): No need to flush.
  (initialize_transcoded_ports): Adapt.
* libguile/read.c (scm_i_scan_for_encoding): Adapt to buffering
  changes.
* libguile/rw.c (scm_write_string_partial): Adapt to buffering changes.
* libguile/strports.c: Adapt to the fact that we don't manage the
  buffer.  Probably room for speed improvements here...
* libguile/vports.c (soft_port_get_natural_buffer_sizes): New function.
  Adapt the rest of the file for the new buffering regime.
* test-suite/tests/r6rs-ports.test ("8.2.10 Output ports"): Custom
  binary output ports need to be flushed before you can rely on the
  write! procedure having been called.  Add necessary flush-port
  invocations.
  ("8.2.6  Input and output ports"): Transcoded ports now have an
  internal buffer by default.  This test checks that the characters are
  transcoded one at a time, so to do that, call setvbuf on the
  transcoded port to remove the buffer.
* test-suite/tests/web-client.test (run-with-http-transcript): Fix for
  different flushing regime on soft ports.  (The vestigial flush
  procedure is now called after each write, which is not what the test
  was expecting.)
* test-suite/standalone/test-scm-c-read.c: Update for changes to the C
  interface for defining port types.
* doc/ref/api-io.texi (Ports): Update to discuss buffering in a generic
  way, and to remove a hand-wavey paragraph describing string ports as
  "interesting and powerful".
  (Reading, Writing): Remove placeholder comments.  Document
  `scm_lfwrite'.
  (Buffering): New section.
  (File Ports): Link to buffering.
  (I/O Extensions): Join subnodes into parent and describe new API,
  including buffering API.
* doc/ref/posix.texi (Ports and File Descriptors): Link to buffering.
  Remove unread-char etc, as they are documented elsewhere.
  (Pipes, Network Sockets and Communication): Link to buffering.
2016-04-06 19:21:44 +02:00
Andy Wingo
e8eeeeb1d4 Port close functions return void
* libguile/ports.h (scm_t_ptob_descriptor): The port close function now
  returns void.
  (scm_set_port_close): Adapt prototype.
* libguile/ports.c (scm_close_port): Always return true if we managed to
  call the close function.  There's no other sensible result; exceptions
  are handled, well, exceptionally.

* libguile/fports.c (fport_close)
* libguile/r6rs-ports.c (custom_binary_port_close, transcoded_port_close):
* libguile/vports.c (soft_port_close): Adapt.

* doc/ref/api-io.texi (Port Implementation): Update.
2016-04-05 15:16:26 +02:00