summaryrefslogtreecommitdiff
path: root/libguile/ports.h
Commit message (Expand)AuthorAgeFilesLines
* 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! Andy Wingo2017-02-081-1/+2
* 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. Andy Wingo2016-08-311-5/+14
* Remove SCM_I_MAX_PORT_TYPE_COUNT...* libguile/ports.h (SCM_I_MAX_PORT_TYPE_COUNT): Remove unused CPP definition. Andy Wingo2016-08-281-3/+0
* 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. Andy Wingo2016-06-081-0/+1
* 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. Andy Wingo2016-05-301-0/+2
* 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. Andy Wingo2016-05-301-2/+9
* 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. Andy Wingo2016-05-241-0/+1
* 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!. Andy Wingo2016-05-221-3/+0
* 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. Andy Wingo2016-05-201-0/+4
* Update port mode bits documentation....* libguile/ports.h: Update documentation of port mode bits. Andy Wingo2016-05-141-10/+9
* 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. Andy Wingo2016-05-131-24/+22
* Make scm_t_ptob_descriptor private....* libguile/goops.c: Use port internals header. * libguile/ports-internal.h (scm_t_port_type_flags) (struct scm_t_ptob_descriptor): Make private. * libguile/ports.h: Adapt. Andy Wingo2016-05-131-30/+1
* 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. Andy Wingo2016-05-131-21/+3
* 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. Andy Wingo2016-05-131-51/+0
* 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. Andy Wingo2016-05-131-16/+0
* 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. Andy Wingo2016-05-131-3/+0
* 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. Andy Wingo2016-05-131-3/+0
* 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. Andy Wingo2016-05-131-0/+3
* 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. Andy Wingo2016-05-131-1/+2
* 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. Andy Wingo2016-05-041-0/+3
* 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. Andy Wingo2016-05-041-12/+11
* 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. Andy Wingo2016-05-031-1/+1
* 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. Andy Wingo2016-05-011-1/+1
* 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. Andy Wingo2016-04-301-0/+6
* 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. Andy Wingo2016-04-301-2/+7
* 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. Andy Wingo2016-04-281-38/+0
* 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. Andy Wingo2016-04-261-1/+0
* 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. Andy Wingo2016-04-261-1/+0
* 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. Andy Wingo2016-04-261-8/+0
* 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. Andy Wingo2016-04-261-8/+0
* 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. Andy Wingo2016-04-261-1/+0
* 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. Andy Wingo2016-04-231-2/+0
* 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. Andy Wingo2016-04-231-2/+0
* 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. Andy Wingo2016-04-231-1/+0
* 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. Andy Wingo2016-04-231-2/+0
* 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. Andy Wingo2016-04-221-12/+0
* 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. Andy Wingo2016-04-221-1/+0
* 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. Andy Wingo2016-04-221-81/+0
* 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. Andy Wingo2016-04-201-54/+69
* 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. Andy Wingo2016-04-191-7/+11
* 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. Andy Wingo2016-04-191-14/+30
* 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. Andy Wingo2016-04-181-10/+12
* 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. Andy Wingo2016-04-171-2/+1
* 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. Andy Wingo2016-04-171-2/+2
* 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. Andy Wingo2016-04-111-6/+8
* 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. Andy Wingo2016-04-061-101/+117
* 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. Andy Wingo2016-04-051-2/+2
* Remove port equal functions...* doc/ref/api-io.texi (Port Implementation): Remove mention of port equal functions. * NEWS: Update. * libguile/ports.c (scm_set_port_equalp): Remove. * libguile/ports.h (scm_t_ptob_descriptor): Remove equalp function. Andy Wingo2016-04-041-2/+0
* Remove port free functions; just close instead...* libguile/ports.h (scm_t_port_type_flags): Replace SCM_PORT_TYPE_HAS_FLUSH with SCM_PORT_TYPE_NEEDS_CLOSE_ON_GC. (scm_t_ptob_descriptor): Remove free function. * libguile/ports.c (scm_set_port_needs_close_on_gc): New function. (scm_set_port_flush): Don't set flags. (scm_c_make_port_with_encoding, scm_close_port): Use the new flag to determine when to add a finalizer and also when to include the port in the weak set. (scm_set_port_free): Remove. (do_close, finalize_port): Close port instead of calling free function. * libguile/r6rs-ports.c (initialize_transcoded_ports): * libguile/vports.c (scm_make_sfptob): * libguile/fports.c (scm_make_fptob): Mark these ports as needing close on GC. * libguile/fports.c (fport_free): Remove. * NEWS: Update. * doc/ref/api-io.texi (Port Implementation): Update. Andy Wingo2016-04-041-3/+4
* Remove port mark functions...* doc/ref/api-io.texi (Port Implementation): Remove documentation. * libguile/ports.c (scm_set_port_mark): Remove function. * libguile/ports.h (scm_t_ptob_descriptor): Remove mark function. * NEWS: Add entry. Andy Wingo2016-04-041-2/+0