Prepare 'setvbuf' to support for non-file ports.
[bpt/guile.git] / libguile / r6rs-ports.c
CommitLineData
c9d55a7e 1/* Copyright (C) 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc.
1ee2c72e
LC
2 *
3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
1ee2c72e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
1ee2c72e
LC
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
1ee2c72e
LC
17 */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#ifdef HAVE_UNISTD_H
24# include <unistd.h>
25#endif
26
27#include <string.h>
28#include <stdio.h>
29#include <assert.h>
30
31#include "libguile/_scm.h"
32#include "libguile/bytevectors.h"
33#include "libguile/chars.h"
34#include "libguile/eval.h"
35#include "libguile/r6rs-ports.h"
36#include "libguile/strings.h"
37#include "libguile/validate.h"
38#include "libguile/values.h"
39#include "libguile/vectors.h"
40
41
42\f
43/* Unimplemented features. */
44
45
46/* Transoders are currently not implemented since Guile 1.8 is not
47 Unicode-capable. Thus, most of the code here assumes the use of the
48 binary transcoder. */
49static inline void
50transcoders_not_implemented (void)
51{
52 fprintf (stderr, "%s: warning: transcoders not implemented\n",
53 PACKAGE_NAME);
54}
55
56\f
57/* End-of-file object. */
58
59SCM_DEFINE (scm_eof_object, "eof-object", 0, 0, 0,
60 (void),
61 "Return the end-of-file object.")
62#define FUNC_NAME s_scm_eof_object
63{
64 return (SCM_EOF_VAL);
65}
66#undef FUNC_NAME
67
68\f
69/* Input ports. */
70
71#ifndef MIN
72# define MIN(a,b) ((a) < (b) ? (a) : (b))
73#endif
74
75/* Bytevector input ports or "bip" for short. */
76static scm_t_bits bytevector_input_port_type = 0;
77
78static inline SCM
79make_bip (SCM bv)
80{
81 SCM port;
82 char *c_bv;
83 unsigned c_len;
84 scm_t_port *c_port;
85 const unsigned long mode_bits = SCM_OPN | SCM_RDNG;
86
a653d32a
AR
87 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
88
1ee2c72e 89 port = scm_new_port_table_entry (bytevector_input_port_type);
96128014
LC
90 c_port = SCM_PTAB_ENTRY (port);
91
92 /* Match the expectation of `binary-port?'. */
93 c_port->encoding = NULL;
1ee2c72e
LC
94
95 /* Prevent BV from being GC'd. */
96 SCM_SETSTREAM (port, SCM_UNPACK (bv));
97
98 /* Have the port directly access the bytevector. */
99 c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv);
100 c_len = SCM_BYTEVECTOR_LENGTH (bv);
101
1ee2c72e
LC
102 c_port->read_pos = c_port->read_buf = (unsigned char *) c_bv;
103 c_port->read_end = (unsigned char *) c_bv + c_len;
104 c_port->read_buf_size = c_len;
105
106 /* Mark PORT as open, readable and unbuffered (hmm, how elegant...). */
107 SCM_SET_CELL_TYPE (port, bytevector_input_port_type | mode_bits);
108
a653d32a
AR
109 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
110
1ee2c72e
LC
111 return port;
112}
113
1ee2c72e
LC
114static int
115bip_fill_input (SCM port)
116{
117 int result;
118 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
119
120 if (c_port->read_pos >= c_port->read_end)
121 result = EOF;
122 else
123 result = (int) *c_port->read_pos;
124
125 return result;
126}
127
f1ce9199
LC
128static scm_t_off
129bip_seek (SCM port, scm_t_off offset, int whence)
1ee2c72e
LC
130#define FUNC_NAME "bip_seek"
131{
f1ce9199 132 scm_t_off c_result = 0;
1ee2c72e
LC
133 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
134
135 switch (whence)
136 {
137 case SEEK_CUR:
138 offset += c_port->read_pos - c_port->read_buf;
139 /* Fall through. */
140
141 case SEEK_SET:
c89b4529 142 if (c_port->read_buf + offset <= c_port->read_end)
1ee2c72e
LC
143 {
144 c_port->read_pos = c_port->read_buf + offset;
145 c_result = offset;
146 }
147 else
148 scm_out_of_range (FUNC_NAME, scm_from_int (offset));
149 break;
150
151 case SEEK_END:
152 if (c_port->read_end - offset >= c_port->read_buf)
153 {
154 c_port->read_pos = c_port->read_end - offset;
155 c_result = c_port->read_pos - c_port->read_buf;
156 }
157 else
158 scm_out_of_range (FUNC_NAME, scm_from_int (offset));
159 break;
160
161 default:
162 scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
163 "invalid `seek' parameter");
164 }
165
166 return c_result;
167}
168#undef FUNC_NAME
169
170
171/* Instantiate the bytevector input port type. */
172static inline void
173initialize_bytevector_input_ports (void)
174{
175 bytevector_input_port_type =
176 scm_make_port_type ("r6rs-bytevector-input-port", bip_fill_input,
177 NULL);
178
1ee2c72e
LC
179 scm_set_port_seek (bytevector_input_port_type, bip_seek);
180}
181
182
183SCM_DEFINE (scm_open_bytevector_input_port,
184 "open-bytevector-input-port", 1, 1, 0,
185 (SCM bv, SCM transcoder),
186 "Return an input port whose contents are drawn from "
187 "bytevector @var{bv}.")
188#define FUNC_NAME s_scm_open_bytevector_input_port
189{
190 SCM_VALIDATE_BYTEVECTOR (1, bv);
191 if (!SCM_UNBNDP (transcoder) && !scm_is_false (transcoder))
192 transcoders_not_implemented ();
193
194 return (make_bip (bv));
195}
196#undef FUNC_NAME
197
198\f
199/* Custom binary ports. The following routines are shared by input and
200 output custom binary ports. */
201
202#define SCM_CBP_GET_POSITION_PROC(_port) \
203 SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 1)
204#define SCM_CBP_SET_POSITION_PROC(_port) \
205 SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 2)
206#define SCM_CBP_CLOSE_PROC(_port) \
207 SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 3)
208
f1ce9199
LC
209static scm_t_off
210cbp_seek (SCM port, scm_t_off offset, int whence)
1ee2c72e
LC
211#define FUNC_NAME "cbp_seek"
212{
213 SCM result;
f1ce9199 214 scm_t_off c_result = 0;
1ee2c72e
LC
215
216 switch (whence)
217 {
218 case SEEK_CUR:
219 {
220 SCM get_position_proc;
221
222 get_position_proc = SCM_CBP_GET_POSITION_PROC (port);
223 if (SCM_LIKELY (scm_is_true (get_position_proc)))
224 result = scm_call_0 (get_position_proc);
225 else
226 scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
c9d55a7e
LC
227 "R6RS custom binary port with "
228 "`port-position' support");
229 c_result = scm_to_int (result);
230 if (offset == 0)
231 /* We just want to know the current position. */
232 break;
233
234 offset += c_result;
1ee2c72e
LC
235 /* Fall through. */
236 }
237
238 case SEEK_SET:
239 {
240 SCM set_position_proc;
241
242 set_position_proc = SCM_CBP_SET_POSITION_PROC (port);
243 if (SCM_LIKELY (scm_is_true (set_position_proc)))
244 result = scm_call_1 (set_position_proc, scm_from_int (offset));
245 else
246 scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
c9d55a7e 247 "seekable R6RS custom binary port");
1ee2c72e
LC
248
249 /* Assuming setting the position succeeded. */
250 c_result = offset;
251 break;
252 }
253
254 default:
255 /* `SEEK_END' cannot be supported. */
256 scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
257 "R6RS custom binary ports do not "
258 "support `SEEK_END'");
259 }
260
261 return c_result;
262}
263#undef FUNC_NAME
264
265static int
266cbp_close (SCM port)
267{
268 SCM close_proc;
269
270 close_proc = SCM_CBP_CLOSE_PROC (port);
271 if (scm_is_true (close_proc))
272 /* Invoke the `close' thunk. */
273 scm_call_0 (close_proc);
274
275 return 1;
276}
277
278\f
279/* Custom binary input port ("cbip" for short). */
280
281static scm_t_bits custom_binary_input_port_type = 0;
282
283/* Size of the buffer embedded in custom binary input ports. */
284#define CBIP_BUFFER_SIZE 4096
285
286/* Return the bytevector associated with PORT. */
287#define SCM_CBIP_BYTEVECTOR(_port) \
288 SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 4)
289
290/* Return the various procedures of PORT. */
291#define SCM_CBIP_READ_PROC(_port) \
292 SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 0)
293
294
295static inline SCM
296make_cbip (SCM read_proc, SCM get_position_proc,
297 SCM set_position_proc, SCM close_proc)
298{
299 SCM port, bv, method_vector;
300 char *c_bv;
301 unsigned c_len;
302 scm_t_port *c_port;
303 const unsigned long mode_bits = SCM_OPN | SCM_RDNG;
304
305 /* Use a bytevector as the underlying buffer. */
306 c_len = CBIP_BUFFER_SIZE;
307 bv = scm_c_make_bytevector (c_len);
308 c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv);
309
310 /* Store the various methods and bytevector in a vector. */
311 method_vector = scm_c_make_vector (5, SCM_BOOL_F);
312 SCM_SIMPLE_VECTOR_SET (method_vector, 4, bv);
313 SCM_SIMPLE_VECTOR_SET (method_vector, 0, read_proc);
314 SCM_SIMPLE_VECTOR_SET (method_vector, 1, get_position_proc);
315 SCM_SIMPLE_VECTOR_SET (method_vector, 2, set_position_proc);
316 SCM_SIMPLE_VECTOR_SET (method_vector, 3, close_proc);
317
a653d32a
AR
318 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
319
1ee2c72e 320 port = scm_new_port_table_entry (custom_binary_input_port_type);
96128014
LC
321 c_port = SCM_PTAB_ENTRY (port);
322
323 /* Match the expectation of `binary-port?'. */
324 c_port->encoding = NULL;
1ee2c72e
LC
325
326 /* Attach it the method vector. */
327 SCM_SETSTREAM (port, SCM_UNPACK (method_vector));
328
329 /* Have the port directly access the buffer (bytevector). */
1ee2c72e
LC
330 c_port->read_pos = c_port->read_buf = (unsigned char *) c_bv;
331 c_port->read_end = (unsigned char *) c_bv;
332 c_port->read_buf_size = c_len;
333
334 /* Mark PORT as open, readable and unbuffered (hmm, how elegant...). */
335 SCM_SET_CELL_TYPE (port, custom_binary_input_port_type | mode_bits);
336
a653d32a
AR
337 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
338
1ee2c72e
LC
339 return port;
340}
341
342static int
343cbip_fill_input (SCM port)
344#define FUNC_NAME "cbip_fill_input"
345{
346 int result;
347 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
348
349 again:
350 if (c_port->read_pos >= c_port->read_end)
351 {
352 /* Invoke the user's `read!' procedure. */
6df03222 353 size_t c_octets, c_requested;
1ee2c72e
LC
354 SCM bv, read_proc, octets;
355
6df03222
LC
356 c_requested = c_port->read_buf_size;
357
1ee2c72e
LC
358 /* Use the bytevector associated with PORT as the buffer passed to the
359 `read!' procedure, thereby avoiding additional allocations. */
360 bv = SCM_CBIP_BYTEVECTOR (port);
361 read_proc = SCM_CBIP_READ_PROC (port);
362
363 /* The assumption here is that C_PORT's internal buffer wasn't changed
364 behind our back. */
365 assert (c_port->read_buf ==
366 (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv));
367 assert ((unsigned) c_port->read_buf_size
368 == SCM_BYTEVECTOR_LENGTH (bv));
369
370 octets = scm_call_3 (read_proc, bv, SCM_INUM0,
6df03222
LC
371 scm_from_size_t (c_requested));
372 c_octets = scm_to_size_t (octets);
373 if (SCM_UNLIKELY (c_octets > c_requested))
374 scm_out_of_range (FUNC_NAME, octets);
1ee2c72e
LC
375
376 c_port->read_pos = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv);
377 c_port->read_end = (unsigned char *) c_port->read_pos + c_octets;
378
379 if (c_octets > 0)
380 goto again;
381 else
382 result = EOF;
383 }
384 else
385 result = (int) *c_port->read_pos;
386
387 return result;
388}
389#undef FUNC_NAME
390
391
392SCM_DEFINE (scm_make_custom_binary_input_port,
393 "make-custom-binary-input-port", 5, 0, 0,
394 (SCM id, SCM read_proc, SCM get_position_proc,
395 SCM set_position_proc, SCM close_proc),
396 "Return a new custom binary input port whose input is drained "
397 "by invoking @var{read_proc} and passing it a bytevector, an "
398 "index where octets should be written, and an octet count.")
399#define FUNC_NAME s_scm_make_custom_binary_input_port
400{
401 SCM_VALIDATE_STRING (1, id);
402 SCM_VALIDATE_PROC (2, read_proc);
403
404 if (!scm_is_false (get_position_proc))
405 SCM_VALIDATE_PROC (3, get_position_proc);
406
407 if (!scm_is_false (set_position_proc))
408 SCM_VALIDATE_PROC (4, set_position_proc);
409
410 if (!scm_is_false (close_proc))
411 SCM_VALIDATE_PROC (5, close_proc);
412
413 return (make_cbip (read_proc, get_position_proc, set_position_proc,
414 close_proc));
415}
416#undef FUNC_NAME
417
418
419/* Instantiate the custom binary input port type. */
420static inline void
421initialize_custom_binary_input_ports (void)
422{
423 custom_binary_input_port_type =
424 scm_make_port_type ("r6rs-custom-binary-input-port",
425 cbip_fill_input, NULL);
426
1ee2c72e
LC
427 scm_set_port_seek (custom_binary_input_port_type, cbp_seek);
428 scm_set_port_close (custom_binary_input_port_type, cbp_close);
429}
430
431
432\f
433/* Binary input. */
434
435/* We currently don't support specific binary input ports. */
436#define SCM_VALIDATE_BINARY_INPUT_PORT SCM_VALIDATE_OPINPORT
437
438SCM_DEFINE (scm_get_u8, "get-u8", 1, 0, 0,
439 (SCM port),
440 "Read an octet from @var{port}, a binary input port, "
441 "blocking as necessary.")
442#define FUNC_NAME s_scm_get_u8
443{
444 SCM result;
445 int c_result;
446
447 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
448
8aa47f26 449 c_result = scm_get_byte_or_eof (port);
1ee2c72e
LC
450 if (c_result == EOF)
451 result = SCM_EOF_VAL;
452 else
453 result = SCM_I_MAKINUM ((unsigned char) c_result);
454
455 return result;
456}
457#undef FUNC_NAME
458
459SCM_DEFINE (scm_lookahead_u8, "lookahead-u8", 1, 0, 0,
460 (SCM port),
461 "Like @code{get-u8} but does not update @var{port} to "
462 "point past the octet.")
463#define FUNC_NAME s_scm_lookahead_u8
464{
8aa47f26 465 int u8;
1ee2c72e
LC
466 SCM result;
467
468 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
469
452c5ad9 470 u8 = scm_peek_byte_or_eof (port);
8aa47f26 471 if (u8 == EOF)
1ee2c72e 472 result = SCM_EOF_VAL;
8aa47f26 473 else
452c5ad9 474 result = SCM_I_MAKINUM ((scm_t_uint8) u8);
1ee2c72e
LC
475
476 return result;
477}
478#undef FUNC_NAME
479
480SCM_DEFINE (scm_get_bytevector_n, "get-bytevector-n", 2, 0, 0,
481 (SCM port, SCM count),
482 "Read @var{count} octets from @var{port}, blocking as "
483 "necessary and return a bytevector containing the octets "
484 "read. If fewer bytes are available, a bytevector smaller "
485 "than @var{count} is returned.")
486#define FUNC_NAME s_scm_get_bytevector_n
487{
488 SCM result;
489 char *c_bv;
490 unsigned c_count;
491 size_t c_read;
492
493 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
494 c_count = scm_to_uint (count);
495
496 result = scm_c_make_bytevector (c_count);
497 c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (result);
498
499 if (SCM_LIKELY (c_count > 0))
500 /* XXX: `scm_c_read ()' does not update the port position. */
501 c_read = scm_c_read (port, c_bv, c_count);
502 else
503 /* Don't invoke `scm_c_read ()' since it may block. */
504 c_read = 0;
505
47f2bce5 506 if (c_read < c_count)
1ee2c72e 507 {
47f2bce5
MW
508 if (c_read == 0)
509 result = SCM_EOF_VAL;
1ee2c72e 510 else
1ee2c72e
LC
511 result = scm_c_shrink_bytevector (result, c_read);
512 }
513
514 return result;
515}
516#undef FUNC_NAME
517
518SCM_DEFINE (scm_get_bytevector_n_x, "get-bytevector-n!", 4, 0, 0,
519 (SCM port, SCM bv, SCM start, SCM count),
520 "Read @var{count} bytes from @var{port} and store them "
521 "in @var{bv} starting at index @var{start}. Return either "
522 "the number of bytes actually read or the end-of-file "
523 "object.")
524#define FUNC_NAME s_scm_get_bytevector_n_x
525{
526 SCM result;
527 char *c_bv;
528 unsigned c_start, c_count, c_len;
529 size_t c_read;
530
531 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
532 SCM_VALIDATE_BYTEVECTOR (2, bv);
533 c_start = scm_to_uint (start);
534 c_count = scm_to_uint (count);
535
536 c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv);
537 c_len = SCM_BYTEVECTOR_LENGTH (bv);
538
539 if (SCM_UNLIKELY (c_start + c_count > c_len))
540 scm_out_of_range (FUNC_NAME, count);
541
542 if (SCM_LIKELY (c_count > 0))
543 c_read = scm_c_read (port, c_bv + c_start, c_count);
544 else
545 /* Don't invoke `scm_c_read ()' since it may block. */
546 c_read = 0;
547
47f2bce5
MW
548 if (c_read == 0 && c_count > 0)
549 result = SCM_EOF_VAL;
1ee2c72e
LC
550 else
551 result = scm_from_size_t (c_read);
552
553 return result;
554}
555#undef FUNC_NAME
556
557
558SCM_DEFINE (scm_get_bytevector_some, "get-bytevector-some", 1, 0, 0,
559 (SCM port),
21bbe22a
MW
560 "Read from @var{port}, blocking as necessary, until bytes "
561 "are available or an end-of-file is reached. Return either "
562 "the end-of-file object or a new bytevector containing some "
563 "of the available bytes (at least one), and update the port "
564 "position to point just past these bytes.")
1ee2c72e
LC
565#define FUNC_NAME s_scm_get_bytevector_some
566{
21bbe22a
MW
567 scm_t_port *pt;
568 size_t size;
569 SCM bv;
1ee2c72e
LC
570
571 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
21bbe22a 572 pt = SCM_PTAB_ENTRY (port);
1ee2c72e 573
21bbe22a
MW
574 if (pt->rw_active == SCM_PORT_WRITE)
575 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
1ee2c72e 576
21bbe22a
MW
577 if (pt->rw_random)
578 pt->rw_active = SCM_PORT_READ;
1ee2c72e 579
21bbe22a 580 if (pt->read_pos >= pt->read_end)
1ee2c72e 581 {
21bbe22a
MW
582 if (scm_fill_input (port) == EOF)
583 return SCM_EOF_VAL;
1ee2c72e 584 }
1ee2c72e 585
21bbe22a
MW
586 size = pt->read_end - pt->read_pos;
587 if (pt->read_buf == pt->putback_buf)
588 size += pt->saved_read_end - pt->saved_read_pos;
1ee2c72e 589
21bbe22a
MW
590 bv = scm_c_make_bytevector (size);
591 scm_take_from_input_buffers
592 (port, (char *) SCM_BYTEVECTOR_CONTENTS (bv), size);
593
594 return bv;
1ee2c72e
LC
595}
596#undef FUNC_NAME
597
598SCM_DEFINE (scm_get_bytevector_all, "get-bytevector-all", 1, 0, 0,
599 (SCM port),
600 "Read from @var{port}, blocking as necessary, until "
601 "the end-of-file is reached. Return either "
602 "a new bytevector containing the data read or the "
603 "end-of-file object (if no data were available).")
604#define FUNC_NAME s_scm_get_bytevector_all
605{
606 SCM result;
607 char *c_bv;
608 unsigned c_len, c_count;
609 size_t c_read, c_total;
610
611 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
612
613 c_len = c_count = 4096;
05762e72 614 c_bv = (char *) scm_gc_malloc_pointerless (c_len, SCM_GC_BYTEVECTOR);
1ee2c72e
LC
615 c_total = c_read = 0;
616
617 do
618 {
619 if (c_total + c_read > c_len)
620 {
621 /* Grow the bytevector. */
622 c_bv = (char *) scm_gc_realloc (c_bv, c_len, c_len * 2,
623 SCM_GC_BYTEVECTOR);
624 c_count = c_len;
625 c_len *= 2;
626 }
627
628 /* `scm_c_read ()' blocks until C_COUNT bytes are available or EOF is
629 reached. */
630 c_read = scm_c_read (port, c_bv + c_total, c_count);
631 c_total += c_read, c_count -= c_read;
632 }
47f2bce5 633 while (c_count == 0);
1ee2c72e
LC
634
635 if (c_total == 0)
636 {
637 result = SCM_EOF_VAL;
638 scm_gc_free (c_bv, c_len, SCM_GC_BYTEVECTOR);
639 }
640 else
641 {
642 if (c_len > c_total)
643 {
644 /* Shrink the bytevector. */
645 c_bv = (char *) scm_gc_realloc (c_bv, c_len, c_total,
646 SCM_GC_BYTEVECTOR);
647 c_len = (unsigned) c_total;
648 }
649
fb031aba 650 result = scm_c_take_gc_bytevector ((signed char *) c_bv, c_len);
1ee2c72e
LC
651 }
652
653 return result;
654}
655#undef FUNC_NAME
656
657
658\f
659/* Binary output. */
660
661/* We currently don't support specific binary input ports. */
662#define SCM_VALIDATE_BINARY_OUTPUT_PORT SCM_VALIDATE_OPOUTPORT
663
664
665SCM_DEFINE (scm_put_u8, "put-u8", 2, 0, 0,
666 (SCM port, SCM octet),
667 "Write @var{octet} to binary port @var{port}.")
668#define FUNC_NAME s_scm_put_u8
669{
670 scm_t_uint8 c_octet;
671
672 SCM_VALIDATE_BINARY_OUTPUT_PORT (1, port);
673 c_octet = scm_to_uint8 (octet);
674
675 scm_putc ((char) c_octet, port);
676
677 return SCM_UNSPECIFIED;
678}
679#undef FUNC_NAME
680
681SCM_DEFINE (scm_put_bytevector, "put-bytevector", 2, 2, 0,
682 (SCM port, SCM bv, SCM start, SCM count),
683 "Write the contents of @var{bv} to @var{port}, optionally "
684 "starting at index @var{start} and limiting to @var{count} "
685 "octets.")
686#define FUNC_NAME s_scm_put_bytevector
687{
688 char *c_bv;
689 unsigned c_start, c_count, c_len;
690
691 SCM_VALIDATE_BINARY_OUTPUT_PORT (1, port);
692 SCM_VALIDATE_BYTEVECTOR (2, bv);
693
694 c_len = SCM_BYTEVECTOR_LENGTH (bv);
695 c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv);
696
d223c3fc 697 if (!scm_is_eq (start, SCM_UNDEFINED))
1ee2c72e
LC
698 {
699 c_start = scm_to_uint (start);
700
d223c3fc 701 if (!scm_is_eq (count, SCM_UNDEFINED))
1ee2c72e
LC
702 {
703 c_count = scm_to_uint (count);
704 if (SCM_UNLIKELY (c_start + c_count > c_len))
705 scm_out_of_range (FUNC_NAME, count);
706 }
707 else
708 {
709 if (SCM_UNLIKELY (c_start >= c_len))
710 scm_out_of_range (FUNC_NAME, start);
711 else
712 c_count = c_len - c_start;
713 }
714 }
715 else
716 c_start = 0, c_count = c_len;
717
718 scm_c_write (port, c_bv + c_start, c_count);
719
720 return SCM_UNSPECIFIED;
721}
722#undef FUNC_NAME
723
7f6c3f8f
MW
724SCM_DEFINE (scm_unget_bytevector, "unget-bytevector", 2, 2, 0,
725 (SCM port, SCM bv, SCM start, SCM count),
726 "Unget the contents of @var{bv} to @var{port}, optionally "
727 "starting at index @var{start} and limiting to @var{count} "
728 "octets.")
729#define FUNC_NAME s_scm_unget_bytevector
730{
731 unsigned char *c_bv;
732 size_t c_start, c_count, c_len;
733
734 SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
735 SCM_VALIDATE_BYTEVECTOR (2, bv);
736
737 c_len = SCM_BYTEVECTOR_LENGTH (bv);
738 c_bv = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv);
739
740 if (!scm_is_eq (start, SCM_UNDEFINED))
741 {
742 c_start = scm_to_size_t (start);
743
744 if (!scm_is_eq (count, SCM_UNDEFINED))
745 {
746 c_count = scm_to_size_t (count);
747 if (SCM_UNLIKELY (c_start + c_count > c_len))
748 scm_out_of_range (FUNC_NAME, count);
749 }
750 else
751 {
752 if (SCM_UNLIKELY (c_start >= c_len))
753 scm_out_of_range (FUNC_NAME, start);
754 else
755 c_count = c_len - c_start;
756 }
757 }
758 else
759 c_start = 0, c_count = c_len;
760
761 scm_unget_bytes (c_bv + c_start, c_count, port);
762
763 return SCM_UNSPECIFIED;
764}
765#undef FUNC_NAME
766
1ee2c72e
LC
767
768\f
769/* Bytevector output port ("bop" for short). */
770
771/* Implementation of "bops".
772
773 Each bop has an internal buffer, of type `scm_t_bop_buffer', attached to
774 it. The procedure returned along with the output port is actually an
775 applicable SMOB. The SMOB holds a reference to the port. When applied,
776 the SMOB swallows the port's internal buffer, turning it into a
777 bytevector, and resets it.
778
779 XXX: Access to a bop's internal buffer is not thread-safe. */
780
781static scm_t_bits bytevector_output_port_type = 0;
782
783SCM_SMOB (bytevector_output_port_procedure,
784 "r6rs-bytevector-output-port-procedure",
785 0);
786
787#define SCM_GC_BOP "r6rs-bytevector-output-port"
788#define SCM_BOP_BUFFER_INITIAL_SIZE 4096
789
790/* Representation of a bop's internal buffer. */
791typedef struct
792{
793 size_t total_len;
794 size_t len;
795 size_t pos;
796 char *buffer;
797} scm_t_bop_buffer;
798
799
800/* Accessing a bop's buffer. */
801#define SCM_BOP_BUFFER(_port) \
802 ((scm_t_bop_buffer *) SCM_STREAM (_port))
803#define SCM_SET_BOP_BUFFER(_port, _buf) \
804 (SCM_SETSTREAM ((_port), (scm_t_bits) (_buf)))
805
806
807static inline void
808bop_buffer_init (scm_t_bop_buffer *buf)
809{
810 buf->total_len = buf->len = buf->pos = 0;
811 buf->buffer = NULL;
812}
813
814static inline void
815bop_buffer_grow (scm_t_bop_buffer *buf, size_t min_size)
816{
817 char *new_buf;
818 size_t new_size;
819
820 for (new_size = buf->total_len
821 ? buf->total_len : SCM_BOP_BUFFER_INITIAL_SIZE;
822 new_size < min_size;
823 new_size *= 2);
824
825 if (buf->buffer)
826 new_buf = scm_gc_realloc ((void *) buf->buffer, buf->total_len,
827 new_size, SCM_GC_BOP);
828 else
05762e72 829 new_buf = scm_gc_malloc_pointerless (new_size, SCM_GC_BOP);
1ee2c72e
LC
830
831 buf->buffer = new_buf;
832 buf->total_len = new_size;
833}
834
835static inline SCM
836make_bop (void)
837{
838 SCM port, bop_proc;
839 scm_t_port *c_port;
840 scm_t_bop_buffer *buf;
841 const unsigned long mode_bits = SCM_OPN | SCM_WRTNG;
842
a653d32a
AR
843 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
844
1ee2c72e 845 port = scm_new_port_table_entry (bytevector_output_port_type);
96128014
LC
846 c_port = SCM_PTAB_ENTRY (port);
847
848 /* Match the expectation of `binary-port?'. */
849 c_port->encoding = NULL;
1ee2c72e
LC
850
851 buf = (scm_t_bop_buffer *) scm_gc_malloc (sizeof (* buf), SCM_GC_BOP);
852 bop_buffer_init (buf);
853
1ee2c72e
LC
854 c_port->write_buf = c_port->write_pos = c_port->write_end = NULL;
855 c_port->write_buf_size = 0;
856
857 SCM_SET_BOP_BUFFER (port, buf);
858
859 /* Mark PORT as open and writable. */
860 SCM_SET_CELL_TYPE (port, bytevector_output_port_type | mode_bits);
861
a653d32a
AR
862 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
863
1ee2c72e 864 /* Make the bop procedure. */
a653d32a 865 SCM_NEWSMOB (bop_proc, bytevector_output_port_procedure, buf);
1ee2c72e
LC
866
867 return (scm_values (scm_list_2 (port, bop_proc)));
868}
869
1ee2c72e
LC
870/* Write SIZE octets from DATA to PORT. */
871static void
872bop_write (SCM port, const void *data, size_t size)
873{
874 scm_t_bop_buffer *buf;
875
876 buf = SCM_BOP_BUFFER (port);
877
878 if (buf->pos + size > buf->total_len)
879 bop_buffer_grow (buf, buf->pos + size);
880
881 memcpy (buf->buffer + buf->pos, data, size);
882 buf->pos += size;
883 buf->len = (buf->len > buf->pos) ? buf->len : buf->pos;
884}
885
f1ce9199
LC
886static scm_t_off
887bop_seek (SCM port, scm_t_off offset, int whence)
1ee2c72e
LC
888#define FUNC_NAME "bop_seek"
889{
890 scm_t_bop_buffer *buf;
891
892 buf = SCM_BOP_BUFFER (port);
893 switch (whence)
894 {
895 case SEEK_CUR:
f1ce9199 896 offset += (scm_t_off) buf->pos;
1ee2c72e
LC
897 /* Fall through. */
898
899 case SEEK_SET:
900 if (offset < 0 || (unsigned) offset > buf->len)
901 scm_out_of_range (FUNC_NAME, scm_from_int (offset));
902 else
903 buf->pos = offset;
904 break;
905
906 case SEEK_END:
907 if (offset < 0 || (unsigned) offset >= buf->len)
908 scm_out_of_range (FUNC_NAME, scm_from_int (offset));
909 else
910 buf->pos = buf->len - (offset + 1);
911 break;
912
913 default:
914 scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
915 "invalid `seek' parameter");
916 }
917
918 return buf->pos;
919}
920#undef FUNC_NAME
921
922/* Fetch data from a bop. */
923SCM_SMOB_APPLY (bytevector_output_port_procedure,
924 bop_proc_apply, 0, 0, 0, (SCM bop_proc))
925{
a653d32a 926 SCM bv;
1ee2c72e
LC
927 scm_t_bop_buffer *buf, result_buf;
928
a653d32a 929 buf = (scm_t_bop_buffer *) SCM_SMOB_DATA (bop_proc);
1ee2c72e
LC
930
931 result_buf = *buf;
932 bop_buffer_init (buf);
933
934 if (result_buf.len == 0)
fb031aba 935 bv = scm_c_take_gc_bytevector (NULL, 0);
1ee2c72e
LC
936 else
937 {
938 if (result_buf.total_len > result_buf.len)
939 /* Shrink the buffer. */
940 result_buf.buffer = scm_gc_realloc ((void *) result_buf.buffer,
941 result_buf.total_len,
942 result_buf.len,
943 SCM_GC_BOP);
944
fb031aba
AW
945 bv = scm_c_take_gc_bytevector ((signed char *) result_buf.buffer,
946 result_buf.len);
1ee2c72e
LC
947 }
948
949 return bv;
950}
951
1ee2c72e
LC
952SCM_DEFINE (scm_open_bytevector_output_port,
953 "open-bytevector-output-port", 0, 1, 0,
954 (SCM transcoder),
955 "Return two values: an output port and a procedure. The latter "
956 "should be called with zero arguments to obtain a bytevector "
957 "containing the data accumulated by the port.")
958#define FUNC_NAME s_scm_open_bytevector_output_port
959{
960 if (!SCM_UNBNDP (transcoder) && !scm_is_false (transcoder))
961 transcoders_not_implemented ();
962
963 return (make_bop ());
964}
965#undef FUNC_NAME
966
967static inline void
968initialize_bytevector_output_ports (void)
969{
970 bytevector_output_port_type =
971 scm_make_port_type ("r6rs-bytevector-output-port",
972 NULL, bop_write);
973
974 scm_set_port_seek (bytevector_output_port_type, bop_seek);
1ee2c72e
LC
975}
976
977\f
978/* Custom binary output port ("cbop" for short). */
979
980static scm_t_bits custom_binary_output_port_type;
981
982/* Return the various procedures of PORT. */
983#define SCM_CBOP_WRITE_PROC(_port) \
984 SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 0)
985
986
987static inline SCM
988make_cbop (SCM write_proc, SCM get_position_proc,
989 SCM set_position_proc, SCM close_proc)
990{
991 SCM port, method_vector;
992 scm_t_port *c_port;
993 const unsigned long mode_bits = SCM_OPN | SCM_WRTNG;
994
995 /* Store the various methods and bytevector in a vector. */
996 method_vector = scm_c_make_vector (4, SCM_BOOL_F);
997 SCM_SIMPLE_VECTOR_SET (method_vector, 0, write_proc);
998 SCM_SIMPLE_VECTOR_SET (method_vector, 1, get_position_proc);
999 SCM_SIMPLE_VECTOR_SET (method_vector, 2, set_position_proc);
1000 SCM_SIMPLE_VECTOR_SET (method_vector, 3, close_proc);
1001
a653d32a
AR
1002 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
1003
1ee2c72e 1004 port = scm_new_port_table_entry (custom_binary_output_port_type);
96128014
LC
1005 c_port = SCM_PTAB_ENTRY (port);
1006
1007 /* Match the expectation of `binary-port?'. */
1008 c_port->encoding = NULL;
1ee2c72e
LC
1009
1010 /* Attach it the method vector. */
1011 SCM_SETSTREAM (port, SCM_UNPACK (method_vector));
1012
1013 /* Have the port directly access the buffer (bytevector). */
1ee2c72e
LC
1014 c_port->write_buf = c_port->write_pos = c_port->write_end = NULL;
1015 c_port->write_buf_size = c_port->read_buf_size = 0;
1016
1017 /* Mark PORT as open, writable and unbuffered. */
1018 SCM_SET_CELL_TYPE (port, custom_binary_output_port_type | mode_bits);
1019
a653d32a
AR
1020 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
1021
1ee2c72e
LC
1022 return port;
1023}
1024
1025/* Write SIZE octets from DATA to PORT. */
1026static void
1027cbop_write (SCM port, const void *data, size_t size)
1028#define FUNC_NAME "cbop_write"
1029{
1030 long int c_result;
1031 size_t c_written;
1032 SCM bv, write_proc, result;
1033
1034 /* XXX: Allocating a new bytevector at each `write' call is inefficient,
1035 but necessary since (1) we don't control the lifetime of the buffer
1036 pointed to by DATA, and (2) the `write!' procedure could capture the
1037 bytevector it is passed. */
1038 bv = scm_c_make_bytevector (size);
1039 memcpy (SCM_BYTEVECTOR_CONTENTS (bv), data, size);
1040
1041 write_proc = SCM_CBOP_WRITE_PROC (port);
1042
1043 /* Since the `write' procedure of Guile's ports has type `void', it must
1044 try hard to write exactly SIZE bytes, regardless of how many bytes the
1045 sink can handle. */
1046 for (c_written = 0;
1047 c_written < size;
1048 c_written += c_result)
1049 {
1050 result = scm_call_3 (write_proc, bv,
1051 scm_from_size_t (c_written),
1052 scm_from_size_t (size - c_written));
1053
1054 c_result = scm_to_long (result);
1055 if (SCM_UNLIKELY (c_result < 0
1056 || (size_t) c_result > (size - c_written)))
1057 scm_wrong_type_arg_msg (FUNC_NAME, 0, result,
1058 "R6RS custom binary output port `write!' "
1059 "returned a incorrect integer");
1060 }
1061}
1062#undef FUNC_NAME
1063
1064
1065SCM_DEFINE (scm_make_custom_binary_output_port,
1066 "make-custom-binary-output-port", 5, 0, 0,
1067 (SCM id, SCM write_proc, SCM get_position_proc,
1068 SCM set_position_proc, SCM close_proc),
1069 "Return a new custom binary output port whose output is drained "
1070 "by invoking @var{write_proc} and passing it a bytevector, an "
1071 "index where octets should be written, and an octet count.")
1072#define FUNC_NAME s_scm_make_custom_binary_output_port
1073{
1074 SCM_VALIDATE_STRING (1, id);
1075 SCM_VALIDATE_PROC (2, write_proc);
1076
1077 if (!scm_is_false (get_position_proc))
1078 SCM_VALIDATE_PROC (3, get_position_proc);
1079
1080 if (!scm_is_false (set_position_proc))
1081 SCM_VALIDATE_PROC (4, set_position_proc);
1082
1083 if (!scm_is_false (close_proc))
1084 SCM_VALIDATE_PROC (5, close_proc);
1085
1086 return (make_cbop (write_proc, get_position_proc, set_position_proc,
1087 close_proc));
1088}
1089#undef FUNC_NAME
1090
1091
1092/* Instantiate the custom binary output port type. */
1093static inline void
1094initialize_custom_binary_output_ports (void)
1095{
1096 custom_binary_output_port_type =
1097 scm_make_port_type ("r6rs-custom-binary-output-port",
1098 NULL, cbop_write);
1099
1ee2c72e
LC
1100 scm_set_port_seek (custom_binary_output_port_type, cbp_seek);
1101 scm_set_port_close (custom_binary_output_port_type, cbp_close);
1102}
1103
1104\f
1044537d
AR
1105/* Transcoded ports ("tp" for short). */
1106static scm_t_bits transcoded_port_type = 0;
1107
1108#define TP_INPUT_BUFFER_SIZE 4096
1109
1110#define SCM_TP_BINARY_PORT(_port) SCM_PACK (SCM_STREAM (_port))
1111
1112static inline SCM
1113make_tp (SCM binary_port, unsigned long mode)
1114{
1115 SCM port;
1116 scm_t_port *c_port;
1117 const unsigned long mode_bits = SCM_OPN | mode;
1118
1119 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
1120
1121 port = scm_new_port_table_entry (transcoded_port_type);
1122
1123 SCM_SETSTREAM (port, SCM_UNPACK (binary_port));
1124
1125 SCM_SET_CELL_TYPE (port, transcoded_port_type | mode_bits);
1126
1127 if (SCM_INPUT_PORT_P (port))
1128 {
1129 c_port = SCM_PTAB_ENTRY (port);
1130 c_port->read_buf = scm_gc_malloc_pointerless (TP_INPUT_BUFFER_SIZE,
1131 "port buffer");
1132 c_port->read_pos = c_port->read_end = c_port->read_buf;
1133 c_port->read_buf_size = TP_INPUT_BUFFER_SIZE;
1134
1135 SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) & ~SCM_BUF0);
1136 }
1137
1138 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
1139
1140 return port;
1141}
1142
1143static void
1144tp_write (SCM port, const void *data, size_t size)
1145{
1146 scm_c_write (SCM_TP_BINARY_PORT (port), data, size);
1147}
1148
1149static int
1150tp_fill_input (SCM port)
1151{
1152 size_t count;
1153 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
1154 SCM bport = SCM_TP_BINARY_PORT (port);
1155 scm_t_port *c_bport = SCM_PTAB_ENTRY (bport);
1156
1157 /* We can't use `scm_c_read' here, since it blocks until the whole
1158 block has been read or EOF. */
1159
1160 if (c_bport->rw_active == SCM_PORT_WRITE)
1161 scm_force_output (bport);
1162
1163 if (c_bport->read_pos >= c_bport->read_end)
1164 scm_fill_input (bport);
1165
1166 count = c_bport->read_end - c_bport->read_pos;
1167 if (count > c_port->read_buf_size)
1168 count = c_port->read_buf_size;
1169
1170 memcpy (c_port->read_buf, c_bport->read_pos, count);
1171 c_bport->read_pos += count;
1172
1173 if (c_bport->rw_random)
1174 c_bport->rw_active = SCM_PORT_READ;
1175
1176 if (count == 0)
1177 return EOF;
1178 else
1179 {
1180 c_port->read_pos = c_port->read_buf;
1181 c_port->read_end = c_port->read_buf + count;
1182 return *c_port->read_buf;
1183 }
1184}
1185
1186static void
1187tp_flush (SCM port)
1188{
1189 SCM binary_port = SCM_TP_BINARY_PORT (port);
1190 scm_t_port *c_port = SCM_PTAB_ENTRY (port);
1191 size_t count = c_port->write_pos - c_port->write_buf;
1192
dfb572a7
AR
1193 /* As the runtime will try to flush all ports upon exit, we test for
1194 the underlying port still being open here. Otherwise, when you
1195 would explicitly close the underlying port and the transcoded port
1196 still had data outstanding, you'd get an exception on Guile exit.
1197
1198 We just throw away the data when the underlying port is closed. */
1199
1200 if (SCM_OPOUTPORTP (binary_port))
1201 scm_c_write (binary_port, c_port->write_buf, count);
1044537d
AR
1202
1203 c_port->write_pos = c_port->write_buf;
1204 c_port->rw_active = SCM_PORT_NEITHER;
1205
dfb572a7
AR
1206 if (SCM_OPOUTPORTP (binary_port))
1207 scm_force_output (binary_port);
1044537d
AR
1208}
1209
1210static int
1211tp_close (SCM port)
1212{
1213 if (SCM_OUTPUT_PORT_P (port))
1214 tp_flush (port);
1215 return scm_is_true (scm_close_port (SCM_TP_BINARY_PORT (port))) ? 0 : -1;
1216}
1217
1218static inline void
1219initialize_transcoded_ports (void)
1220{
1221 transcoded_port_type =
1222 scm_make_port_type ("r6rs-transcoded-port", tp_fill_input, tp_write);
1223
1224 scm_set_port_flush (transcoded_port_type, tp_flush);
1225 scm_set_port_close (transcoded_port_type, tp_close);
1226}
1227
1228SCM_DEFINE (scm_i_make_transcoded_port,
1229 "%make-transcoded-port", 1, 0, 0,
1230 (SCM port),
1231 "Return a new port which reads and writes to @var{port}")
1232#define FUNC_NAME s_scm_i_make_transcoded_port
1233{
1234 SCM result;
1235 unsigned long mode = 0;
1236
1237 SCM_VALIDATE_PORT (SCM_ARG1, port);
1238
1239 if (scm_is_true (scm_output_port_p (port)))
1240 mode |= SCM_WRTNG;
1241 else if (scm_is_true (scm_input_port_p (port)))
1242 mode |= SCM_RDNG;
1243
1244 result = make_tp (port, mode);
1245
1246 /* FIXME: We should actually close `port' "in a special way" here,
1247 according to R6RS. As there is no way to do that in Guile without
1248 rendering the underlying port unusable for our purposes as well, we
1249 just leave it open. */
1250
1251 return result;
1252}
1253#undef FUNC_NAME
1254
1255\f
a6c377f7
AR
1256/* Textual I/O */
1257
1258SCM_DEFINE (scm_get_string_n_x,
1259 "get-string-n!", 4, 0, 0,
1260 (SCM port, SCM str, SCM start, SCM count),
1261 "Read up to @var{count} characters from @var{port} into "
1262 "@var{str}, starting at @var{start}. If no characters "
1263 "can be read before the end of file is encountered, the end "
1264 "of file object is returned. Otherwise, the number of "
1265 "characters read is returned.")
1266#define FUNC_NAME s_scm_get_string_n_x
1267{
1268 size_t c_start, c_count, c_len, c_end, j;
1269 scm_t_wchar c;
1270
1271 SCM_VALIDATE_OPINPORT (1, port);
1272 SCM_VALIDATE_STRING (2, str);
1273 c_len = scm_c_string_length (str);
1274 c_start = scm_to_size_t (start);
1275 c_count = scm_to_size_t (count);
1276 c_end = c_start + c_count;
1277
1278 if (SCM_UNLIKELY (c_end > c_len))
1279 scm_out_of_range (FUNC_NAME, count);
1280
1281 for (j = c_start; j < c_end; j++)
1282 {
1283 c = scm_getc (port);
1284 if (c == EOF)
1285 {
1286 size_t chars_read = j - c_start;
1287 return chars_read == 0 ? SCM_EOF_VAL : scm_from_size_t (chars_read);
1288 }
1289 scm_c_string_set_x (str, j, SCM_MAKE_CHAR (c));
1290 }
1291 return count;
1292}
1293#undef FUNC_NAME
1294
1295\f
1ee2c72e
LC
1296/* Initialization. */
1297
c0062328
LC
1298void
1299scm_register_r6rs_ports (void)
1300{
1301 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1302 "scm_init_r6rs_ports",
1303 (scm_t_extension_init_func) scm_init_r6rs_ports,
1304 NULL);
1305}
1306
1ee2c72e
LC
1307void
1308scm_init_r6rs_ports (void)
1309{
62e9a9b7 1310#include "libguile/r6rs-ports.x"
1ee2c72e
LC
1311
1312 initialize_bytevector_input_ports ();
1313 initialize_custom_binary_input_ports ();
1314 initialize_bytevector_output_ports ();
1315 initialize_custom_binary_output_ports ();
1044537d 1316 initialize_transcoded_ports ();
1ee2c72e 1317}