use the new finalizer helpers
[bpt/guile.git] / libguile / ports.c
1 /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
2 * 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
18 */
19
20
21 \f
22 /* Headers. */
23
24 #define _LARGEFILE64_SOURCE /* ask for stat64 etc */
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include <errno.h>
32 #include <fcntl.h> /* for chsize on mingw */
33 #include <assert.h>
34 #include <iconv.h>
35 #include <uniconv.h>
36 #include <unistr.h>
37 #include <striconveh.h>
38
39 #include <assert.h>
40
41 #include "libguile/_scm.h"
42 #include "libguile/async.h"
43 #include "libguile/deprecation.h"
44 #include "libguile/eval.h"
45 #include "libguile/fports.h" /* direct access for seek and truncate */
46 #include "libguile/goops.h"
47 #include "libguile/smob.h"
48 #include "libguile/chars.h"
49 #include "libguile/dynwind.h"
50
51 #include "libguile/keywords.h"
52 #include "libguile/hashtab.h"
53 #include "libguile/root.h"
54 #include "libguile/strings.h"
55 #include "libguile/mallocs.h"
56 #include "libguile/validate.h"
57 #include "libguile/ports.h"
58 #include "libguile/vectors.h"
59 #include "libguile/weak-set.h"
60 #include "libguile/fluids.h"
61 #include "libguile/eq.h"
62
63 #ifdef HAVE_STRING_H
64 #include <string.h>
65 #endif
66
67 #ifdef HAVE_IO_H
68 #include <io.h>
69 #endif
70
71 #ifdef HAVE_UNISTD_H
72 #include <unistd.h>
73 #endif
74
75 #ifdef HAVE_SYS_IOCTL_H
76 #include <sys/ioctl.h>
77 #endif
78
79 /* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize
80 already, but have this code here in case that wasn't so in past versions,
81 or perhaps to help other minimal DOS environments.
82
83 gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which
84 might be possibilities if we've got other systems without ftruncate. */
85
86 #if defined HAVE_CHSIZE && ! defined HAVE_FTRUNCATE
87 #define ftruncate(fd, size) chsize (fd, size)
88 #undef HAVE_FTRUNCATE
89 #define HAVE_FTRUNCATE 1
90 #endif
91
92 \f
93 /* The port kind table --- a dynamically resized array of port types. */
94
95
96 /* scm_ptobs scm_numptob
97 * implement a dynamically resized array of ptob records.
98 * Indexes into this table are used when generating type
99 * tags for smobjects (if you know a tag you can get an index and conversely).
100 */
101 static scm_t_ptob_descriptor **scm_ptobs = NULL;
102 static long scm_numptob = 0; /* Number of port types. */
103 static long scm_ptobs_size = 0; /* Number of slots in the port type
104 table. */
105 static scm_i_pthread_mutex_t scm_ptobs_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
106 SCM_PTHREAD_ATFORK_LOCK_STATIC_MUTEX (scm_ptobs_lock);
107
108 long
109 scm_c_num_port_types (void)
110 {
111 long ret;
112
113 scm_i_pthread_mutex_lock (&scm_ptobs_lock);
114 ret = scm_numptob;
115 scm_i_pthread_mutex_unlock (&scm_ptobs_lock);
116
117 return ret;
118 }
119
120 scm_t_ptob_descriptor*
121 scm_c_port_type_ref (long ptobnum)
122 {
123 scm_t_ptob_descriptor *ret = NULL;
124
125 scm_i_pthread_mutex_lock (&scm_ptobs_lock);
126
127 if (0 <= ptobnum && ptobnum < scm_numptob)
128 ret = scm_ptobs[ptobnum];
129
130 scm_i_pthread_mutex_unlock (&scm_ptobs_lock);
131
132 if (!ret)
133 scm_out_of_range ("scm_c_port_type_ref", scm_from_long (ptobnum));
134
135 return ret;
136 }
137
138 long
139 scm_c_port_type_add_x (scm_t_ptob_descriptor *desc)
140 {
141 long ret = -1;
142
143 scm_i_pthread_mutex_lock (&scm_ptobs_lock);
144
145 if (scm_numptob + 1 < SCM_I_MAX_PORT_TYPE_COUNT)
146 {
147 if (scm_numptob == scm_ptobs_size)
148 {
149 unsigned long old_size = scm_ptobs_size;
150 scm_t_ptob_descriptor **old_ptobs = scm_ptobs;
151
152 /* Currently there are only 9 predefined port types, so one
153 resize will cover it. */
154 scm_ptobs_size = old_size + 10;
155
156 if (scm_ptobs_size >= SCM_I_MAX_PORT_TYPE_COUNT)
157 scm_ptobs_size = SCM_I_MAX_PORT_TYPE_COUNT;
158
159 scm_ptobs = scm_gc_malloc (sizeof (*scm_ptobs) * scm_ptobs_size,
160 "scm_ptobs");
161
162 memcpy (scm_ptobs, old_ptobs, sizeof (*scm_ptobs) * scm_numptob);
163 }
164
165 ret = scm_numptob++;
166 scm_ptobs[ret] = desc;
167 }
168
169 scm_i_pthread_mutex_unlock (&scm_ptobs_lock);
170
171 if (ret < 0)
172 scm_out_of_range ("scm_c_port_type_add_x", scm_from_long (scm_numptob));
173
174 return ret;
175 }
176
177 /*
178 * We choose to use an interface similar to the smob interface with
179 * fill_input and write as standard fields, passed to the port
180 * type constructor, and optional fields set by setters.
181 */
182
183 static void
184 flush_port_default (SCM port SCM_UNUSED)
185 {
186 }
187
188 static void
189 end_input_default (SCM port SCM_UNUSED, int offset SCM_UNUSED)
190 {
191 }
192
193 scm_t_bits
194 scm_make_port_type (char *name,
195 int (*fill_input) (SCM port),
196 void (*write) (SCM port, const void *data, size_t size))
197 {
198 scm_t_ptob_descriptor *desc;
199 long ptobnum;
200
201 desc = scm_gc_malloc_pointerless (sizeof (*desc), "port-type");
202 memset (desc, 0, sizeof (*desc));
203
204 desc->name = name;
205 desc->print = scm_port_print;
206 desc->write = write;
207 desc->flush = flush_port_default;
208 desc->end_input = end_input_default;
209 desc->fill_input = fill_input;
210
211 ptobnum = scm_c_port_type_add_x (desc);
212
213 /* Make a class object if GOOPS is present. */
214 if (SCM_UNPACK (scm_port_class[0]) != 0)
215 scm_make_port_classes (ptobnum, name);
216
217 return scm_tc7_port + ptobnum * 256;
218 }
219
220 void
221 scm_set_port_mark (scm_t_bits tc, SCM (*mark) (SCM))
222 {
223 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->mark = mark;
224 }
225
226 void
227 scm_set_port_free (scm_t_bits tc, size_t (*free) (SCM))
228 {
229 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->free = free;
230 }
231
232 void
233 scm_set_port_print (scm_t_bits tc, int (*print) (SCM exp, SCM port,
234 scm_print_state *pstate))
235 {
236 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->print = print;
237 }
238
239 void
240 scm_set_port_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
241 {
242 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->equalp = equalp;
243 }
244
245 void
246 scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
247 {
248 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->close = close;
249 }
250
251 void
252 scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port))
253 {
254 scm_t_ptob_descriptor *ptob = scm_c_port_type_ref (SCM_TC2PTOBNUM (tc));
255 ptob->flush = flush;
256 ptob->flags |= SCM_PORT_TYPE_HAS_FLUSH;
257 }
258
259 void
260 scm_set_port_end_input (scm_t_bits tc, void (*end_input) (SCM port, int offset))
261 {
262 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->end_input = end_input;
263 }
264
265 void
266 scm_set_port_seek (scm_t_bits tc, scm_t_off (*seek) (SCM, scm_t_off, int))
267 {
268 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->seek = seek;
269 }
270
271 void
272 scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM, scm_t_off))
273 {
274 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->truncate = truncate;
275 }
276
277 void
278 scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) (SCM))
279 {
280 scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->input_waiting = input_waiting;
281 }
282
283 \f
284
285 /* Standard ports --- current input, output, error, and more(!). */
286
287 static SCM cur_inport_fluid = SCM_BOOL_F;
288 static SCM cur_outport_fluid = SCM_BOOL_F;
289 static SCM cur_errport_fluid = SCM_BOOL_F;
290 static SCM cur_loadport_fluid = SCM_BOOL_F;
291
292 SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
293 (),
294 "Return the current input port. This is the default port used\n"
295 "by many input procedures. Initially, @code{current-input-port}\n"
296 "returns the @dfn{standard input} in Unix and C terminology.")
297 #define FUNC_NAME s_scm_current_input_port
298 {
299 if (scm_is_true (cur_inport_fluid))
300 return scm_fluid_ref (cur_inport_fluid);
301 else
302 return SCM_BOOL_F;
303 }
304 #undef FUNC_NAME
305
306 SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
307 (),
308 "Return the current output port. This is the default port used\n"
309 "by many output procedures. Initially,\n"
310 "@code{current-output-port} returns the @dfn{standard output} in\n"
311 "Unix and C terminology.")
312 #define FUNC_NAME s_scm_current_output_port
313 {
314 if (scm_is_true (cur_outport_fluid))
315 return scm_fluid_ref (cur_outport_fluid);
316 else
317 return SCM_BOOL_F;
318 }
319 #undef FUNC_NAME
320
321 SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
322 (),
323 "Return the port to which errors and warnings should be sent (the\n"
324 "@dfn{standard error} in Unix and C terminology).")
325 #define FUNC_NAME s_scm_current_error_port
326 {
327 if (scm_is_true (cur_errport_fluid))
328 return scm_fluid_ref (cur_errport_fluid);
329 else
330 return SCM_BOOL_F;
331 }
332 #undef FUNC_NAME
333
334 SCM
335 scm_current_warning_port (void)
336 {
337 static SCM cwp_var = SCM_BOOL_F;
338
339 if (scm_is_false (cwp_var))
340 cwp_var = scm_c_private_lookup ("guile", "current-warning-port");
341
342 return scm_call_0 (scm_variable_ref (cwp_var));
343 }
344
345 SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
346 (),
347 "Return the current-load-port.\n"
348 "The load port is used internally by @code{primitive-load}.")
349 #define FUNC_NAME s_scm_current_load_port
350 {
351 return scm_fluid_ref (cur_loadport_fluid);
352 }
353 #undef FUNC_NAME
354
355 SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
356 (SCM port),
357 "@deffnx {Scheme Procedure} set-current-output-port port\n"
358 "@deffnx {Scheme Procedure} set-current-error-port port\n"
359 "Change the ports returned by @code{current-input-port},\n"
360 "@code{current-output-port} and @code{current-error-port}, respectively,\n"
361 "so that they use the supplied @var{port} for input or output.")
362 #define FUNC_NAME s_scm_set_current_input_port
363 {
364 SCM oinp = scm_fluid_ref (cur_inport_fluid);
365 SCM_VALIDATE_OPINPORT (1, port);
366 scm_fluid_set_x (cur_inport_fluid, port);
367 return oinp;
368 }
369 #undef FUNC_NAME
370
371
372 SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
373 (SCM port),
374 "Set the current default output port to @var{port}.")
375 #define FUNC_NAME s_scm_set_current_output_port
376 {
377 SCM ooutp = scm_fluid_ref (cur_outport_fluid);
378 port = SCM_COERCE_OUTPORT (port);
379 SCM_VALIDATE_OPOUTPORT (1, port);
380 scm_fluid_set_x (cur_outport_fluid, port);
381 return ooutp;
382 }
383 #undef FUNC_NAME
384
385
386 SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
387 (SCM port),
388 "Set the current default error port to @var{port}.")
389 #define FUNC_NAME s_scm_set_current_error_port
390 {
391 SCM oerrp = scm_fluid_ref (cur_errport_fluid);
392 port = SCM_COERCE_OUTPORT (port);
393 SCM_VALIDATE_OPOUTPORT (1, port);
394 scm_fluid_set_x (cur_errport_fluid, port);
395 return oerrp;
396 }
397 #undef FUNC_NAME
398
399
400 SCM
401 scm_set_current_warning_port (SCM port)
402 {
403 static SCM cwp_var = SCM_BOOL_F;
404
405 if (scm_is_false (cwp_var))
406 cwp_var = scm_c_private_lookup ("guile", "current-warning-port");
407
408 return scm_call_1 (scm_variable_ref (cwp_var), port);
409 }
410
411
412 void
413 scm_dynwind_current_input_port (SCM port)
414 #define FUNC_NAME NULL
415 {
416 SCM_VALIDATE_OPINPORT (1, port);
417 scm_dynwind_fluid (cur_inport_fluid, port);
418 }
419 #undef FUNC_NAME
420
421 void
422 scm_dynwind_current_output_port (SCM port)
423 #define FUNC_NAME NULL
424 {
425 port = SCM_COERCE_OUTPORT (port);
426 SCM_VALIDATE_OPOUTPORT (1, port);
427 scm_dynwind_fluid (cur_outport_fluid, port);
428 }
429 #undef FUNC_NAME
430
431 void
432 scm_dynwind_current_error_port (SCM port)
433 #define FUNC_NAME NULL
434 {
435 port = SCM_COERCE_OUTPORT (port);
436 SCM_VALIDATE_OPOUTPORT (1, port);
437 scm_dynwind_fluid (cur_errport_fluid, port);
438 }
439 #undef FUNC_NAME
440
441 void
442 scm_i_dynwind_current_load_port (SCM port)
443 {
444 scm_dynwind_fluid (cur_loadport_fluid, port);
445 }
446
447
448 \f
449
450 /* Retrieving a port's mode. */
451
452 /* Return the flags that characterize a port based on the mode
453 * string used to open a file for that port.
454 *
455 * See PORT FLAGS in scm.h
456 */
457
458 static long
459 scm_i_mode_bits_n (SCM modes)
460 {
461 return (SCM_OPN
462 | (scm_i_string_contains_char (modes, 'r')
463 || scm_i_string_contains_char (modes, '+') ? SCM_RDNG : 0)
464 | (scm_i_string_contains_char (modes, 'w')
465 || scm_i_string_contains_char (modes, 'a')
466 || scm_i_string_contains_char (modes, '+') ? SCM_WRTNG : 0)
467 | (scm_i_string_contains_char (modes, '0') ? SCM_BUF0 : 0)
468 | (scm_i_string_contains_char (modes, 'l') ? SCM_BUFLINE : 0));
469 }
470
471 long
472 scm_mode_bits (char *modes)
473 {
474 return scm_i_mode_bits (scm_from_locale_string (modes));
475 }
476
477 long
478 scm_i_mode_bits (SCM modes)
479 {
480 long bits;
481
482 if (!scm_is_string (modes))
483 scm_wrong_type_arg_msg (NULL, 0, modes, "string");
484
485 bits = scm_i_mode_bits_n (modes);
486 scm_remember_upto_here_1 (modes);
487 return bits;
488 }
489
490 /* Return the mode flags from an open port.
491 * Some modes such as "append" are only used when opening
492 * a file and are not returned here. */
493
494 SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
495 (SCM port),
496 "Return the port modes associated with the open port @var{port}.\n"
497 "These will not necessarily be identical to the modes used when\n"
498 "the port was opened, since modes such as \"append\" which are\n"
499 "used only during port creation are not retained.")
500 #define FUNC_NAME s_scm_port_mode
501 {
502 char modes[4];
503 modes[0] = '\0';
504
505 port = SCM_COERCE_OUTPORT (port);
506 SCM_VALIDATE_OPPORT (1, port);
507 if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
508 if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
509 strcpy (modes, "r+");
510 else
511 strcpy (modes, "r");
512 }
513 else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
514 strcpy (modes, "w");
515 if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
516 strcat (modes, "0");
517
518 return scm_from_latin1_string (modes);
519 }
520 #undef FUNC_NAME
521
522
523 \f
524
525 /* The port table --- a weak set of all ports.
526
527 We need a global registry of ports to flush them all at exit, and to
528 get all the ports matching a file descriptor. */
529 SCM scm_i_port_weak_set;
530
531
532 \f
533
534 /* Port finalization. */
535
536 struct do_free_data
537 {
538 scm_t_ptob_descriptor *ptob;
539 SCM port;
540 };
541
542 static SCM
543 do_free (void *body_data)
544 {
545 struct do_free_data *data = body_data;
546
547 /* `close' is for explicit `close-port' by user. `free' is for this
548 purpose: ports collected by the GC. */
549 data->ptob->free (data->port);
550
551 return SCM_BOOL_T;
552 }
553
554 /* Finalize the object (a port) pointed to by PTR. */
555 static void
556 finalize_port (GC_PTR ptr, GC_PTR data)
557 {
558 SCM port = SCM_PACK_POINTER (ptr);
559
560 if (!SCM_PORTP (port))
561 abort ();
562
563 if (SCM_OPENP (port))
564 {
565 struct do_free_data data;
566
567 SCM_CLR_PORT_OPEN_FLAG (port);
568
569 data.ptob = SCM_PORT_DESCRIPTOR (port);
570 data.port = port;
571
572 scm_internal_catch (SCM_BOOL_T, do_free, &data,
573 scm_handle_by_message_noexit, NULL);
574
575 scm_gc_ports_collected++;
576 }
577 }
578
579
580 \f
581
582 SCM
583 scm_c_make_port_with_encoding (scm_t_bits tag, unsigned long mode_bits,
584 const char *encoding,
585 scm_t_string_failed_conversion_handler handler,
586 scm_t_bits stream)
587 {
588 SCM ret;
589 scm_t_port *entry;
590 scm_t_ptob_descriptor *ptob;
591
592 entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
593 ptob = scm_c_port_type_ref (SCM_TC2PTOBNUM (tag));
594
595 ret = scm_words (tag | mode_bits, 3);
596 SCM_SET_CELL_WORD_1 (ret, (scm_t_bits) entry);
597 SCM_SET_CELL_WORD_2 (ret, (scm_t_bits) ptob);
598
599 entry->lock = scm_gc_malloc_pointerless (sizeof (*entry->lock), "port lock");
600 scm_i_pthread_mutex_init (entry->lock, scm_i_pthread_mutexattr_recursive);
601
602 entry->file_name = SCM_BOOL_F;
603 entry->rw_active = SCM_PORT_NEITHER;
604 entry->port = ret;
605 entry->stream = stream;
606 entry->encoding = encoding ? scm_gc_strdup (encoding, "port") : NULL;
607 if (encoding && strcmp (encoding, "UTF-8") == 0)
608 entry->encoding_mode = SCM_PORT_ENCODING_MODE_UTF8;
609 else
610 entry->encoding_mode = SCM_PORT_ENCODING_MODE_ICONV;
611 entry->ilseq_handler = handler;
612 entry->iconv_descriptors = NULL;
613
614 if (SCM_PORT_DESCRIPTOR (ret)->free)
615 scm_i_set_finalizer (SCM2PTR (ret), finalize_port, NULL);
616
617 if (SCM_PORT_DESCRIPTOR (ret)->flags & SCM_PORT_TYPE_HAS_FLUSH)
618 scm_weak_set_add_x (scm_i_port_weak_set, ret);
619
620 return ret;
621 }
622
623 SCM
624 scm_c_make_port (scm_t_bits tag, unsigned long mode_bits, scm_t_bits stream)
625 {
626 return scm_c_make_port_with_encoding (tag, mode_bits,
627 scm_i_default_port_encoding (),
628 scm_i_get_conversion_strategy (SCM_BOOL_F),
629 stream);
630 }
631
632 SCM
633 scm_new_port_table_entry (scm_t_bits tag)
634 {
635 return scm_c_make_port (tag, 0, 0);
636 }
637
638 \f
639
640 /* Predicates. */
641
642 SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
643 (SCM x),
644 "Return a boolean indicating whether @var{x} is a port.\n"
645 "Equivalent to @code{(or (input-port? @var{x}) (output-port?\n"
646 "@var{x}))}.")
647 #define FUNC_NAME s_scm_port_p
648 {
649 return scm_from_bool (SCM_PORTP (x));
650 }
651 #undef FUNC_NAME
652
653 SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
654 (SCM x),
655 "Return @code{#t} if @var{x} is an input port, otherwise return\n"
656 "@code{#f}. Any object satisfying this predicate also satisfies\n"
657 "@code{port?}.")
658 #define FUNC_NAME s_scm_input_port_p
659 {
660 return scm_from_bool (SCM_INPUT_PORT_P (x));
661 }
662 #undef FUNC_NAME
663
664 SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
665 (SCM x),
666 "Return @code{#t} if @var{x} is an output port, otherwise return\n"
667 "@code{#f}. Any object satisfying this predicate also satisfies\n"
668 "@code{port?}.")
669 #define FUNC_NAME s_scm_output_port_p
670 {
671 x = SCM_COERCE_OUTPORT (x);
672 return scm_from_bool (SCM_OUTPUT_PORT_P (x));
673 }
674 #undef FUNC_NAME
675
676 SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
677 (SCM port),
678 "Return @code{#t} if @var{port} is closed or @code{#f} if it is\n"
679 "open.")
680 #define FUNC_NAME s_scm_port_closed_p
681 {
682 SCM_VALIDATE_PORT (1, port);
683 return scm_from_bool (!SCM_OPPORTP (port));
684 }
685 #undef FUNC_NAME
686
687 SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
688 (SCM x),
689 "Return @code{#t} if @var{x} is an end-of-file object; otherwise\n"
690 "return @code{#f}.")
691 #define FUNC_NAME s_scm_eof_object_p
692 {
693 return scm_from_bool (SCM_EOF_OBJECT_P (x));
694 }
695 #undef FUNC_NAME
696
697
698 \f
699
700 /* Closing ports. */
701
702 static void close_iconv_descriptors (scm_t_iconv_descriptors *id);
703
704 /* scm_close_port
705 * Call the close operation on a port object.
706 * see also scm_close.
707 */
708 SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
709 (SCM port),
710 "Close the specified port object. Return @code{#t} if it\n"
711 "successfully closes a port or @code{#f} if it was already\n"
712 "closed. An exception may be raised if an error occurs, for\n"
713 "example when flushing buffered output. See also @ref{Ports and\n"
714 "File Descriptors, close}, for a procedure which can close file\n"
715 "descriptors.")
716 #define FUNC_NAME s_scm_close_port
717 {
718 scm_t_port *p;
719 int rv;
720
721 port = SCM_COERCE_OUTPORT (port);
722
723 SCM_VALIDATE_PORT (1, port);
724 if (SCM_CLOSEDP (port))
725 return SCM_BOOL_F;
726
727 p = SCM_PTAB_ENTRY (port);
728 SCM_CLR_PORT_OPEN_FLAG (port);
729
730 if (SCM_PORT_DESCRIPTOR (port)->flags & SCM_PORT_TYPE_HAS_FLUSH)
731 scm_weak_set_remove_x (scm_i_port_weak_set, port);
732
733 if (SCM_PORT_DESCRIPTOR (port)->close)
734 /* Note! This may throw an exception. Anything after this point
735 should be resilient to non-local exits. */
736 rv = SCM_PORT_DESCRIPTOR (port)->close (port);
737 else
738 rv = 0;
739
740 if (p->iconv_descriptors)
741 {
742 /* If we don't get here, the iconv_descriptors finalizer will
743 clean up. */
744 close_iconv_descriptors (p->iconv_descriptors);
745 p->iconv_descriptors = NULL;
746 }
747
748 return scm_from_bool (rv >= 0);
749 }
750 #undef FUNC_NAME
751
752 SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
753 (SCM port),
754 "Close the specified input port object. The routine has no effect if\n"
755 "the file has already been closed. An exception may be raised if an\n"
756 "error occurs. The value returned is unspecified.\n\n"
757 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
758 "which can close file descriptors.")
759 #define FUNC_NAME s_scm_close_input_port
760 {
761 SCM_VALIDATE_INPUT_PORT (1, port);
762 scm_close_port (port);
763 return SCM_UNSPECIFIED;
764 }
765 #undef FUNC_NAME
766
767 SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
768 (SCM port),
769 "Close the specified output port object. The routine has no effect if\n"
770 "the file has already been closed. An exception may be raised if an\n"
771 "error occurs. The value returned is unspecified.\n\n"
772 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
773 "which can close file descriptors.")
774 #define FUNC_NAME s_scm_close_output_port
775 {
776 port = SCM_COERCE_OUTPORT (port);
777 SCM_VALIDATE_OUTPUT_PORT (1, port);
778 scm_close_port (port);
779 return SCM_UNSPECIFIED;
780 }
781 #undef FUNC_NAME
782
783
784 \f
785
786 /* Encoding characters to byte streams, and decoding byte streams to
787 characters. */
788
789 /* A fluid specifying the default encoding for newly created ports. If it is
790 a string, that is the encoding. If it is #f, it is in the "native"
791 (Latin-1) encoding. */
792 SCM_VARIABLE (default_port_encoding_var, "%default-port-encoding");
793
794 static int scm_port_encoding_init = 0;
795
796 /* Use ENCODING as the default encoding for future ports. */
797 void
798 scm_i_set_default_port_encoding (const char *encoding)
799 {
800 if (!scm_port_encoding_init
801 || !scm_is_fluid (SCM_VARIABLE_REF (default_port_encoding_var)))
802 scm_misc_error (NULL, "tried to set port encoding fluid before it is initialized",
803 SCM_EOL);
804
805 if (encoding == NULL
806 || !strcmp (encoding, "ASCII")
807 || !strcmp (encoding, "ANSI_X3.4-1968")
808 || !strcmp (encoding, "ISO-8859-1"))
809 scm_fluid_set_x (SCM_VARIABLE_REF (default_port_encoding_var), SCM_BOOL_F);
810 else
811 scm_fluid_set_x (SCM_VARIABLE_REF (default_port_encoding_var),
812 scm_from_locale_string (encoding));
813 }
814
815 /* Return the name of the default encoding for newly created ports; a
816 return value of NULL means "ISO-8859-1". */
817 const char *
818 scm_i_default_port_encoding (void)
819 {
820 if (!scm_port_encoding_init)
821 return NULL;
822 else if (!scm_is_fluid (SCM_VARIABLE_REF (default_port_encoding_var)))
823 return NULL;
824 else
825 {
826 SCM encoding;
827
828 encoding = scm_fluid_ref (SCM_VARIABLE_REF (default_port_encoding_var));
829 if (!scm_is_string (encoding))
830 return NULL;
831 else
832 return scm_i_string_chars (encoding);
833 }
834 }
835
836 static void
837 finalize_iconv_descriptors (GC_PTR ptr, GC_PTR data)
838 {
839 close_iconv_descriptors (ptr);
840 }
841
842 static scm_t_iconv_descriptors *
843 open_iconv_descriptors (const char *encoding, int reading, int writing)
844 {
845 scm_t_iconv_descriptors *id;
846 iconv_t input_cd, output_cd;
847
848 input_cd = (iconv_t) -1;
849 output_cd = (iconv_t) -1;
850
851 if (reading)
852 {
853 /* Open an input iconv conversion descriptor, from ENCODING
854 to UTF-8. We choose UTF-8, not UTF-32, because iconv
855 implementations can typically convert from anything to
856 UTF-8, but not to UTF-32 (see
857 <http://lists.gnu.org/archive/html/bug-libunistring/2010-09/msg00007.html>). */
858
859 /* Assume opening an iconv descriptor causes about 16 KB of
860 allocation. */
861 scm_gc_register_allocation (16 * 1024);
862
863 scm_i_lock_iconv ();
864 input_cd = iconv_open ("UTF-8", encoding);
865 scm_i_unlock_iconv ();
866 if (input_cd == (iconv_t) -1)
867 goto invalid_encoding;
868 }
869
870 if (writing)
871 {
872 /* Assume opening an iconv descriptor causes about 16 KB of
873 allocation. */
874 scm_gc_register_allocation (16 * 1024);
875
876 scm_i_lock_iconv ();
877 output_cd = iconv_open (encoding, "UTF-8");
878 scm_i_unlock_iconv ();
879 if (output_cd == (iconv_t) -1)
880 {
881 scm_i_lock_iconv ();
882 if (input_cd != (iconv_t) -1)
883 iconv_close (input_cd);
884 scm_i_unlock_iconv ();
885 goto invalid_encoding;
886 }
887 }
888
889 id = scm_gc_malloc_pointerless (sizeof (*id), "iconv descriptors");
890 id->input_cd = input_cd;
891 id->output_cd = output_cd;
892
893 /* Register a finalizer to close the descriptors. */
894 scm_i_set_finalizer (id, finalize_iconv_descriptors, NULL);
895
896 return id;
897
898 invalid_encoding:
899 {
900 SCM err;
901 err = scm_from_locale_string (encoding);
902 scm_misc_error ("open_iconv_descriptors",
903 "invalid or unknown character encoding ~s",
904 scm_list_1 (err));
905 }
906 }
907
908 static void
909 close_iconv_descriptors (scm_t_iconv_descriptors *id)
910 {
911 scm_i_lock_iconv ();
912 if (id->input_cd != (iconv_t) -1)
913 iconv_close (id->input_cd);
914 if (id->output_cd != (iconv_t) -1)
915 iconv_close (id->output_cd);
916 scm_i_unlock_iconv ();
917 id->input_cd = (void *) -1;
918 id->output_cd = (void *) -1;
919 }
920
921 scm_t_iconv_descriptors *
922 scm_i_port_iconv_descriptors (SCM port)
923 {
924 scm_t_port *pt;
925
926 pt = SCM_PTAB_ENTRY (port);
927
928 assert (pt->encoding_mode == SCM_PORT_ENCODING_MODE_ICONV);
929
930 if (!pt->iconv_descriptors)
931 {
932 if (!pt->encoding)
933 pt->encoding = "ISO-8859-1";
934 pt->iconv_descriptors =
935 open_iconv_descriptors (pt->encoding,
936 SCM_INPUT_PORT_P (port),
937 SCM_OUTPUT_PORT_P (port));
938 }
939
940 return pt->iconv_descriptors;
941 }
942
943 void
944 scm_i_set_port_encoding_x (SCM port, const char *encoding)
945 {
946 scm_t_port *pt;
947 scm_t_iconv_descriptors *prev;
948
949 /* Set the character encoding for this port. */
950 pt = SCM_PTAB_ENTRY (port);
951 prev = pt->iconv_descriptors;
952
953 if (encoding == NULL)
954 encoding = "ISO-8859-1";
955
956 if (strcmp (encoding, "UTF-8") == 0)
957 {
958 pt->encoding = "UTF-8";
959 pt->encoding_mode = SCM_PORT_ENCODING_MODE_UTF8;
960 pt->iconv_descriptors = NULL;
961 }
962 else
963 {
964 /* Open descriptors before mutating the port. */
965 pt->iconv_descriptors =
966 open_iconv_descriptors (encoding,
967 SCM_INPUT_PORT_P (port),
968 SCM_OUTPUT_PORT_P (port));
969 pt->encoding = scm_gc_strdup (encoding, "port");
970 pt->encoding_mode = SCM_PORT_ENCODING_MODE_ICONV;
971 }
972
973 if (prev)
974 close_iconv_descriptors (prev);
975 }
976
977 SCM_DEFINE (scm_port_encoding, "port-encoding", 1, 0, 0,
978 (SCM port),
979 "Returns, as a string, the character encoding that @var{port}\n"
980 "uses to interpret its input and output.\n")
981 #define FUNC_NAME s_scm_port_encoding
982 {
983 scm_t_port *pt;
984 const char *enc;
985
986 SCM_VALIDATE_PORT (1, port);
987
988 pt = SCM_PTAB_ENTRY (port);
989 enc = pt->encoding;
990 if (enc)
991 return scm_from_locale_string (pt->encoding);
992 else
993 return SCM_BOOL_F;
994 }
995 #undef FUNC_NAME
996
997 SCM_DEFINE (scm_set_port_encoding_x, "set-port-encoding!", 2, 0, 0,
998 (SCM port, SCM enc),
999 "Sets the character encoding that will be used to interpret all\n"
1000 "port I/O. New ports are created with the encoding\n"
1001 "appropriate for the current locale if @code{setlocale} has \n"
1002 "been called or ISO-8859-1 otherwise\n"
1003 "and this procedure can be used to modify that encoding.\n")
1004 #define FUNC_NAME s_scm_set_port_encoding_x
1005 {
1006 char *enc_str;
1007
1008 SCM_VALIDATE_PORT (1, port);
1009 SCM_VALIDATE_STRING (2, enc);
1010
1011 enc_str = scm_to_locale_string (enc);
1012 scm_i_set_port_encoding_x (port, enc_str);
1013 free (enc_str);
1014
1015 return SCM_UNSPECIFIED;
1016 }
1017 #undef FUNC_NAME
1018
1019
1020 /* This determines how conversions handle unconvertible characters. */
1021 SCM_GLOBAL_VARIABLE (scm_conversion_strategy, "%port-conversion-strategy");
1022 static int scm_conversion_strategy_init = 0;
1023
1024 scm_t_string_failed_conversion_handler
1025 scm_i_get_conversion_strategy (SCM port)
1026 {
1027 SCM encoding;
1028
1029 if (scm_is_false (port))
1030 {
1031 if (!scm_conversion_strategy_init
1032 || !scm_is_fluid (SCM_VARIABLE_REF (scm_conversion_strategy)))
1033 return SCM_FAILED_CONVERSION_QUESTION_MARK;
1034 else
1035 {
1036 encoding = scm_fluid_ref (SCM_VARIABLE_REF (scm_conversion_strategy));
1037 if (scm_is_false (encoding))
1038 return SCM_FAILED_CONVERSION_QUESTION_MARK;
1039 else
1040 return (scm_t_string_failed_conversion_handler) scm_to_int (encoding);
1041 }
1042 }
1043 else
1044 {
1045 scm_t_port *pt;
1046 pt = SCM_PTAB_ENTRY (port);
1047 return pt->ilseq_handler;
1048 }
1049
1050 }
1051
1052 void
1053 scm_i_set_conversion_strategy_x (SCM port,
1054 scm_t_string_failed_conversion_handler handler)
1055 {
1056 SCM strategy;
1057 scm_t_port *pt;
1058
1059 strategy = scm_from_int ((int) handler);
1060
1061 if (scm_is_false (port))
1062 {
1063 /* Set the default encoding for future ports. */
1064 if (!scm_conversion_strategy_init
1065 || !scm_is_fluid (SCM_VARIABLE_REF (scm_conversion_strategy)))
1066 scm_misc_error (NULL, "tried to set conversion strategy fluid before it is initialized",
1067 SCM_EOL);
1068 scm_fluid_set_x (SCM_VARIABLE_REF (scm_conversion_strategy), strategy);
1069 }
1070 else
1071 {
1072 /* Set the character encoding for this port. */
1073 pt = SCM_PTAB_ENTRY (port);
1074 pt->ilseq_handler = handler;
1075 }
1076 }
1077
1078 SCM_DEFINE (scm_port_conversion_strategy, "port-conversion-strategy",
1079 1, 0, 0, (SCM port),
1080 "Returns the behavior of the port when handling a character that\n"
1081 "is not representable in the port's current encoding.\n"
1082 "It returns the symbol @code{error} if unrepresentable characters\n"
1083 "should cause exceptions, @code{substitute} if the port should\n"
1084 "try to replace unrepresentable characters with question marks or\n"
1085 "approximate characters, or @code{escape} if unrepresentable\n"
1086 "characters should be converted to string escapes.\n"
1087 "\n"
1088 "If @var{port} is @code{#f}, then the current default behavior\n"
1089 "will be returned. New ports will have this default behavior\n"
1090 "when they are created.\n")
1091 #define FUNC_NAME s_scm_port_conversion_strategy
1092 {
1093 scm_t_string_failed_conversion_handler h;
1094
1095 SCM_VALIDATE_OPPORT (1, port);
1096
1097 if (!scm_is_false (port))
1098 {
1099 SCM_VALIDATE_OPPORT (1, port);
1100 }
1101
1102 h = scm_i_get_conversion_strategy (port);
1103 if (h == SCM_FAILED_CONVERSION_ERROR)
1104 return scm_from_latin1_symbol ("error");
1105 else if (h == SCM_FAILED_CONVERSION_QUESTION_MARK)
1106 return scm_from_latin1_symbol ("substitute");
1107 else if (h == SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE)
1108 return scm_from_latin1_symbol ("escape");
1109 else
1110 abort ();
1111
1112 /* Never gets here. */
1113 return SCM_UNDEFINED;
1114 }
1115 #undef FUNC_NAME
1116
1117 SCM_DEFINE (scm_set_port_conversion_strategy_x, "set-port-conversion-strategy!",
1118 2, 0, 0,
1119 (SCM port, SCM sym),
1120 "Sets the behavior of the interpreter when outputting a character\n"
1121 "that is not representable in the port's current encoding.\n"
1122 "@var{sym} can be either @code{'error}, @code{'substitute}, or\n"
1123 "@code{'escape}. If it is @code{'error}, an error will be thrown\n"
1124 "when an unconvertible character is encountered. If it is\n"
1125 "@code{'substitute}, then unconvertible characters will \n"
1126 "be replaced with approximate characters, or with question marks\n"
1127 "if no approximately correct character is available.\n"
1128 "If it is @code{'escape},\n"
1129 "it will appear as a hex escape when output.\n"
1130 "\n"
1131 "If @var{port} is an open port, the conversion error behavior\n"
1132 "is set for that port. If it is @code{#f}, it is set as the\n"
1133 "default behavior for any future ports that get created in\n"
1134 "this thread.\n")
1135 #define FUNC_NAME s_scm_set_port_conversion_strategy_x
1136 {
1137 SCM err;
1138 SCM qm;
1139 SCM esc;
1140
1141 if (!scm_is_false (port))
1142 {
1143 SCM_VALIDATE_OPPORT (1, port);
1144 }
1145
1146 err = scm_from_latin1_symbol ("error");
1147 if (scm_is_true (scm_eqv_p (sym, err)))
1148 {
1149 scm_i_set_conversion_strategy_x (port, SCM_FAILED_CONVERSION_ERROR);
1150 return SCM_UNSPECIFIED;
1151 }
1152
1153 qm = scm_from_latin1_symbol ("substitute");
1154 if (scm_is_true (scm_eqv_p (sym, qm)))
1155 {
1156 scm_i_set_conversion_strategy_x (port,
1157 SCM_FAILED_CONVERSION_QUESTION_MARK);
1158 return SCM_UNSPECIFIED;
1159 }
1160
1161 esc = scm_from_latin1_symbol ("escape");
1162 if (scm_is_true (scm_eqv_p (sym, esc)))
1163 {
1164 scm_i_set_conversion_strategy_x (port,
1165 SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE);
1166 return SCM_UNSPECIFIED;
1167 }
1168
1169 SCM_MISC_ERROR ("unknown conversion behavior ~s", scm_list_1 (sym));
1170
1171 return SCM_UNSPECIFIED;
1172 }
1173 #undef FUNC_NAME
1174
1175
1176 \f
1177
1178 /* The port lock. */
1179
1180 static void
1181 lock_port (void *mutex)
1182 {
1183 scm_i_pthread_mutex_lock (mutex);
1184 }
1185
1186 static void
1187 unlock_port (void *mutex)
1188 {
1189 scm_i_pthread_mutex_unlock (mutex);
1190 }
1191
1192 void
1193 scm_dynwind_lock_port (SCM port)
1194 #define FUNC_NAME "dynwind-lock-port"
1195 {
1196 scm_i_pthread_mutex_t *lock;
1197 SCM_VALIDATE_OPPORT (SCM_ARG1, port);
1198 scm_c_lock_port (port, &lock);
1199 if (lock)
1200 {
1201 scm_dynwind_unwind_handler (unlock_port, lock, SCM_F_WIND_EXPLICITLY);
1202 scm_dynwind_rewind_handler (lock_port, lock, 0);
1203 }
1204 }
1205 #undef FUNC_NAME
1206
1207
1208 \f
1209
1210 /* Input. */
1211
1212 int
1213 scm_get_byte_or_eof (SCM port)
1214 {
1215 scm_i_pthread_mutex_t *lock;
1216 int ret;
1217
1218 scm_c_lock_port (port, &lock);
1219 ret = scm_get_byte_or_eof_unlocked (port);
1220 if (lock)
1221 scm_i_pthread_mutex_unlock (lock);
1222
1223 return ret;
1224 }
1225
1226 int
1227 scm_peek_byte_or_eof (SCM port)
1228 {
1229 scm_i_pthread_mutex_t *lock;
1230 int ret;
1231
1232 scm_c_lock_port (port, &lock);
1233 ret = scm_peek_byte_or_eof_unlocked (port);
1234 if (lock)
1235 scm_i_pthread_mutex_unlock (lock);
1236
1237 return ret;
1238 }
1239
1240 /* scm_c_read
1241 *
1242 * Used by an application to read arbitrary number of bytes from an
1243 * SCM port. Same semantics as libc read, except that scm_c_read only
1244 * returns less than SIZE bytes if at end-of-file.
1245 *
1246 * Warning: Doesn't update port line and column counts! */
1247
1248 /* This structure, and the following swap_buffer function, are used
1249 for temporarily swapping a port's own read buffer, and the buffer
1250 that the caller of scm_c_read provides. */
1251 struct port_and_swap_buffer
1252 {
1253 scm_t_port *pt;
1254 unsigned char *buffer;
1255 size_t size;
1256 };
1257
1258 static void
1259 swap_buffer (void *data)
1260 {
1261 struct port_and_swap_buffer *psb = (struct port_and_swap_buffer *) data;
1262 unsigned char *old_buf = psb->pt->read_buf;
1263 size_t old_size = psb->pt->read_buf_size;
1264
1265 /* Make the port use (buffer, size) from the struct. */
1266 psb->pt->read_pos = psb->pt->read_buf = psb->pt->read_end = psb->buffer;
1267 psb->pt->read_buf_size = psb->size;
1268
1269 /* Save the port's old (buffer, size) in the struct. */
1270 psb->buffer = old_buf;
1271 psb->size = old_size;
1272 }
1273
1274 size_t
1275 scm_c_read_unlocked (SCM port, void *buffer, size_t size)
1276 #define FUNC_NAME "scm_c_read"
1277 {
1278 scm_t_port *pt;
1279 size_t n_read = 0, n_available;
1280 struct port_and_swap_buffer psb;
1281
1282 SCM_VALIDATE_OPINPORT (1, port);
1283
1284 pt = SCM_PTAB_ENTRY (port);
1285 if (pt->rw_active == SCM_PORT_WRITE)
1286 SCM_PORT_DESCRIPTOR (port)->flush (port);
1287
1288 if (pt->rw_random)
1289 pt->rw_active = SCM_PORT_READ;
1290
1291 /* Take bytes first from the port's read buffer. */
1292 if (pt->read_pos < pt->read_end)
1293 {
1294 n_available = min (size, pt->read_end - pt->read_pos);
1295 memcpy (buffer, pt->read_pos, n_available);
1296 buffer = (char *) buffer + n_available;
1297 pt->read_pos += n_available;
1298 n_read += n_available;
1299 size -= n_available;
1300 }
1301
1302 /* Avoid the scm_dynwind_* costs if we now have enough data. */
1303 if (size == 0)
1304 return n_read;
1305
1306 /* Now we will call scm_fill_input repeatedly until we have read the
1307 requested number of bytes. (Note that a single scm_fill_input
1308 call does not guarantee to fill the whole of the port's read
1309 buffer.) */
1310 if (pt->read_buf_size <= 1 && pt->encoding == NULL)
1311 {
1312 /* The port that we are reading from is unbuffered - i.e. does
1313 not have its own persistent buffer - but we have a buffer,
1314 provided by our caller, that is the right size for the data
1315 that is wanted. For the following scm_fill_input calls,
1316 therefore, we use the buffer in hand as the port's read
1317 buffer.
1318
1319 We need to make sure that the port's normal (1 byte) buffer
1320 is reinstated in case one of the scm_fill_input () calls
1321 throws an exception; we use the scm_dynwind_* API to achieve
1322 that.
1323
1324 A consequence of this optimization is that the fill_input
1325 functions can't unget characters. That'll push data to the
1326 pushback buffer instead of this psb buffer. */
1327 #if SCM_DEBUG == 1
1328 unsigned char *pback = pt->putback_buf;
1329 #endif
1330 psb.pt = pt;
1331 psb.buffer = buffer;
1332 psb.size = size;
1333 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1334 scm_dynwind_rewind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1335 scm_dynwind_unwind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1336
1337 /* Call scm_fill_input until we have all the bytes that we need,
1338 or we hit EOF. */
1339 while (pt->read_buf_size && (scm_fill_input_unlocked (port) != EOF))
1340 {
1341 pt->read_buf_size -= (pt->read_end - pt->read_pos);
1342 pt->read_pos = pt->read_buf = pt->read_end;
1343 }
1344 #if SCM_DEBUG == 1
1345 if (pback != pt->putback_buf
1346 || pt->read_buf - (unsigned char *) buffer < 0)
1347 scm_misc_error (FUNC_NAME,
1348 "scm_c_read must not call a fill function that pushes "
1349 "back characters onto an unbuffered port", SCM_EOL);
1350 #endif
1351 n_read += pt->read_buf - (unsigned char *) buffer;
1352
1353 /* Reinstate the port's normal buffer. */
1354 scm_dynwind_end ();
1355 }
1356 else
1357 {
1358 /* The port has its own buffer. It is important that we use it,
1359 even if it happens to be smaller than our caller's buffer, so
1360 that a custom port implementation's entry points (in
1361 particular, fill_input) can rely on the buffer always being
1362 the same as they first set up. */
1363 while (size && (scm_fill_input_unlocked (port) != EOF))
1364 {
1365 n_available = min (size, pt->read_end - pt->read_pos);
1366 memcpy (buffer, pt->read_pos, n_available);
1367 buffer = (char *) buffer + n_available;
1368 pt->read_pos += n_available;
1369 n_read += n_available;
1370 size -= n_available;
1371 }
1372 }
1373
1374 return n_read;
1375 }
1376 #undef FUNC_NAME
1377
1378 size_t
1379 scm_c_read (SCM port, void *buffer, size_t size)
1380 {
1381 scm_i_pthread_mutex_t *lock;
1382 size_t ret;
1383
1384 scm_c_lock_port (port, &lock);
1385 ret = scm_c_read_unlocked (port, buffer, size);
1386 if (lock)
1387 scm_i_pthread_mutex_unlock (lock);
1388
1389
1390 return ret;
1391 }
1392
1393 /* Update the line and column number of PORT after consumption of C. */
1394 static inline void
1395 update_port_lf (scm_t_wchar c, SCM port)
1396 {
1397 switch (c)
1398 {
1399 case '\a':
1400 case EOF:
1401 break;
1402 case '\b':
1403 SCM_DECCOL (port);
1404 break;
1405 case '\n':
1406 SCM_INCLINE (port);
1407 break;
1408 case '\r':
1409 SCM_ZEROCOL (port);
1410 break;
1411 case '\t':
1412 SCM_TABCOL (port);
1413 break;
1414 default:
1415 SCM_INCCOL (port);
1416 break;
1417 }
1418 }
1419
1420 #define SCM_MBCHAR_BUF_SIZE (4)
1421
1422 /* Convert the SIZE-byte UTF-8 sequence in UTF8_BUF to a codepoint.
1423 UTF8_BUF is assumed to contain a valid UTF-8 sequence. */
1424 static scm_t_wchar
1425 utf8_to_codepoint (const scm_t_uint8 *utf8_buf, size_t size)
1426 {
1427 scm_t_wchar codepoint;
1428
1429 if (utf8_buf[0] <= 0x7f)
1430 {
1431 assert (size == 1);
1432 codepoint = utf8_buf[0];
1433 }
1434 else if ((utf8_buf[0] & 0xe0) == 0xc0)
1435 {
1436 assert (size == 2);
1437 codepoint = ((scm_t_wchar) utf8_buf[0] & 0x1f) << 6UL
1438 | (utf8_buf[1] & 0x3f);
1439 }
1440 else if ((utf8_buf[0] & 0xf0) == 0xe0)
1441 {
1442 assert (size == 3);
1443 codepoint = ((scm_t_wchar) utf8_buf[0] & 0x0f) << 12UL
1444 | ((scm_t_wchar) utf8_buf[1] & 0x3f) << 6UL
1445 | (utf8_buf[2] & 0x3f);
1446 }
1447 else
1448 {
1449 assert (size == 4);
1450 codepoint = ((scm_t_wchar) utf8_buf[0] & 0x07) << 18UL
1451 | ((scm_t_wchar) utf8_buf[1] & 0x3f) << 12UL
1452 | ((scm_t_wchar) utf8_buf[2] & 0x3f) << 6UL
1453 | (utf8_buf[3] & 0x3f);
1454 }
1455
1456 return codepoint;
1457 }
1458
1459 /* Read a UTF-8 sequence from PORT. On success, return 0 and set
1460 *CODEPOINT to the codepoint that was read, fill BUF with its UTF-8
1461 representation, and set *LEN to the length in bytes. Return
1462 `EILSEQ' on error. */
1463 static int
1464 get_utf8_codepoint (SCM port, scm_t_wchar *codepoint,
1465 scm_t_uint8 buf[SCM_MBCHAR_BUF_SIZE], size_t *len)
1466 {
1467 #define ASSERT_NOT_EOF(b) \
1468 if (SCM_UNLIKELY ((b) == EOF)) \
1469 goto invalid_seq
1470 #define CONSUME_PEEKED_BYTE() \
1471 pt->read_pos++
1472
1473 int byte;
1474 scm_t_port *pt;
1475
1476 *len = 0;
1477 pt = SCM_PTAB_ENTRY (port);
1478
1479 byte = scm_get_byte_or_eof_unlocked (port);
1480 if (byte == EOF)
1481 {
1482 *codepoint = EOF;
1483 return 0;
1484 }
1485
1486 buf[0] = (scm_t_uint8) byte;
1487 *len = 1;
1488
1489 if (buf[0] <= 0x7f)
1490 /* 1-byte form. */
1491 *codepoint = buf[0];
1492 else if (buf[0] >= 0xc2 && buf[0] <= 0xdf)
1493 {
1494 /* 2-byte form. */
1495 byte = scm_peek_byte_or_eof_unlocked (port);
1496 ASSERT_NOT_EOF (byte);
1497
1498 if (SCM_UNLIKELY ((byte & 0xc0) != 0x80))
1499 goto invalid_seq;
1500
1501 CONSUME_PEEKED_BYTE ();
1502 buf[1] = (scm_t_uint8) byte;
1503 *len = 2;
1504
1505 *codepoint = ((scm_t_wchar) buf[0] & 0x1f) << 6UL
1506 | (buf[1] & 0x3f);
1507 }
1508 else if ((buf[0] & 0xf0) == 0xe0)
1509 {
1510 /* 3-byte form. */
1511 byte = scm_peek_byte_or_eof_unlocked (port);
1512 ASSERT_NOT_EOF (byte);
1513
1514 if (SCM_UNLIKELY ((byte & 0xc0) != 0x80
1515 || (buf[0] == 0xe0 && byte < 0xa0)
1516 || (buf[0] == 0xed && byte > 0x9f)))
1517 goto invalid_seq;
1518
1519 CONSUME_PEEKED_BYTE ();
1520 buf[1] = (scm_t_uint8) byte;
1521 *len = 2;
1522
1523 byte = scm_peek_byte_or_eof_unlocked (port);
1524 ASSERT_NOT_EOF (byte);
1525
1526 if (SCM_UNLIKELY ((byte & 0xc0) != 0x80))
1527 goto invalid_seq;
1528
1529 CONSUME_PEEKED_BYTE ();
1530 buf[2] = (scm_t_uint8) byte;
1531 *len = 3;
1532
1533 *codepoint = ((scm_t_wchar) buf[0] & 0x0f) << 12UL
1534 | ((scm_t_wchar) buf[1] & 0x3f) << 6UL
1535 | (buf[2] & 0x3f);
1536 }
1537 else if (buf[0] >= 0xf0 && buf[0] <= 0xf4)
1538 {
1539 /* 4-byte form. */
1540 byte = scm_peek_byte_or_eof_unlocked (port);
1541 ASSERT_NOT_EOF (byte);
1542
1543 if (SCM_UNLIKELY (((byte & 0xc0) != 0x80)
1544 || (buf[0] == 0xf0 && byte < 0x90)
1545 || (buf[0] == 0xf4 && byte > 0x8f)))
1546 goto invalid_seq;
1547
1548 CONSUME_PEEKED_BYTE ();
1549 buf[1] = (scm_t_uint8) byte;
1550 *len = 2;
1551
1552 byte = scm_peek_byte_or_eof_unlocked (port);
1553 ASSERT_NOT_EOF (byte);
1554
1555 if (SCM_UNLIKELY ((byte & 0xc0) != 0x80))
1556 goto invalid_seq;
1557
1558 CONSUME_PEEKED_BYTE ();
1559 buf[2] = (scm_t_uint8) byte;
1560 *len = 3;
1561
1562 byte = scm_peek_byte_or_eof_unlocked (port);
1563 ASSERT_NOT_EOF (byte);
1564
1565 if (SCM_UNLIKELY ((byte & 0xc0) != 0x80))
1566 goto invalid_seq;
1567
1568 CONSUME_PEEKED_BYTE ();
1569 buf[3] = (scm_t_uint8) byte;
1570 *len = 4;
1571
1572 *codepoint = ((scm_t_wchar) buf[0] & 0x07) << 18UL
1573 | ((scm_t_wchar) buf[1] & 0x3f) << 12UL
1574 | ((scm_t_wchar) buf[2] & 0x3f) << 6UL
1575 | (buf[3] & 0x3f);
1576 }
1577 else
1578 goto invalid_seq;
1579
1580 return 0;
1581
1582 invalid_seq:
1583 /* Here we could choose the consume the faulty byte when it's not a
1584 valid starting byte, but it's not a requirement. What Section 3.9
1585 of Unicode 6.0.0 mandates, though, is to not consume a byte that
1586 would otherwise be a valid starting byte. */
1587
1588 return EILSEQ;
1589
1590 #undef CONSUME_PEEKED_BYTE
1591 #undef ASSERT_NOT_EOF
1592 }
1593
1594 /* Likewise, read a byte sequence from PORT, passing it through its
1595 input conversion descriptor. */
1596 static int
1597 get_iconv_codepoint (SCM port, scm_t_wchar *codepoint,
1598 char buf[SCM_MBCHAR_BUF_SIZE], size_t *len)
1599 {
1600 scm_t_iconv_descriptors *id;
1601 int err, byte_read;
1602 size_t bytes_consumed, output_size;
1603 char *output;
1604 scm_t_uint8 utf8_buf[SCM_MBCHAR_BUF_SIZE];
1605
1606 id = scm_i_port_iconv_descriptors (port);
1607
1608 for (output_size = 0, output = (char *) utf8_buf,
1609 bytes_consumed = 0, err = 0;
1610 err == 0 && output_size == 0
1611 && (bytes_consumed == 0 || byte_read != EOF);
1612 bytes_consumed++)
1613 {
1614 char *input;
1615 size_t input_left, output_left, done;
1616
1617 byte_read = scm_get_byte_or_eof_unlocked (port);
1618 if (byte_read == EOF)
1619 {
1620 if (bytes_consumed == 0)
1621 {
1622 *codepoint = (scm_t_wchar) EOF;
1623 *len = 0;
1624 return 0;
1625 }
1626 else
1627 continue;
1628 }
1629
1630 buf[bytes_consumed] = byte_read;
1631
1632 input = buf;
1633 input_left = bytes_consumed + 1;
1634 output_left = sizeof (utf8_buf);
1635
1636 done = iconv (id->input_cd, &input, &input_left, &output, &output_left);
1637 if (done == (size_t) -1)
1638 {
1639 err = errno;
1640 if (err == EINVAL)
1641 /* Missing input: keep trying. */
1642 err = 0;
1643 }
1644 else
1645 output_size = sizeof (utf8_buf) - output_left;
1646 }
1647
1648 if (SCM_UNLIKELY (output_size == 0))
1649 /* An unterminated sequence. */
1650 err = EILSEQ;
1651 else if (SCM_LIKELY (err == 0))
1652 {
1653 /* Convert the UTF8_BUF sequence to a Unicode code point. */
1654 *codepoint = utf8_to_codepoint (utf8_buf, output_size);
1655 *len = bytes_consumed;
1656 }
1657
1658 return err;
1659 }
1660
1661 /* Read a codepoint from PORT and return it in *CODEPOINT. Fill BUF
1662 with the byte representation of the codepoint in PORT's encoding, and
1663 set *LEN to the length in bytes of that representation. Return 0 on
1664 success and an errno value on error. */
1665 static int
1666 get_codepoint (SCM port, scm_t_wchar *codepoint,
1667 char buf[SCM_MBCHAR_BUF_SIZE], size_t *len)
1668 {
1669 int err;
1670 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1671
1672 if (pt->encoding_mode == SCM_PORT_ENCODING_MODE_UTF8)
1673 err = get_utf8_codepoint (port, codepoint, (scm_t_uint8 *) buf, len);
1674 else
1675 err = get_iconv_codepoint (port, codepoint, buf, len);
1676
1677 if (SCM_LIKELY (err == 0))
1678 update_port_lf (*codepoint, port);
1679 else if (pt->ilseq_handler == SCM_ICONVEH_QUESTION_MARK)
1680 {
1681 *codepoint = '?';
1682 err = 0;
1683 update_port_lf (*codepoint, port);
1684 }
1685
1686 return err;
1687 }
1688
1689 /* Read a codepoint from PORT and return it. */
1690 scm_t_wchar
1691 scm_getc_unlocked (SCM port)
1692 #define FUNC_NAME "scm_getc"
1693 {
1694 int err;
1695 size_t len;
1696 scm_t_wchar codepoint;
1697 char buf[SCM_MBCHAR_BUF_SIZE];
1698
1699 err = get_codepoint (port, &codepoint, buf, &len);
1700 if (SCM_UNLIKELY (err != 0))
1701 /* At this point PORT should point past the invalid encoding, as per
1702 R6RS-lib Section 8.2.4. */
1703 scm_decoding_error (FUNC_NAME, err, "input decoding error", port);
1704
1705 return codepoint;
1706 }
1707 #undef FUNC_NAME
1708
1709 scm_t_wchar
1710 scm_getc (SCM port)
1711 {
1712 scm_i_pthread_mutex_t *lock;
1713 scm_t_wchar ret;
1714
1715 scm_c_lock_port (port, &lock);
1716 ret = scm_getc_unlocked (port);
1717 if (lock)
1718 scm_i_pthread_mutex_unlock (lock);
1719
1720
1721 return ret;
1722 }
1723
1724 SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1725 (SCM port),
1726 "Return the next character available from @var{port}, updating\n"
1727 "@var{port} to point to the following character. If no more\n"
1728 "characters are available, the end-of-file object is returned.\n"
1729 "\n"
1730 "When @var{port}'s data cannot be decoded according to its\n"
1731 "character encoding, a @code{decoding-error} is raised and\n"
1732 "@var{port} points past the erroneous byte sequence.\n")
1733 #define FUNC_NAME s_scm_read_char
1734 {
1735 scm_t_wchar c;
1736 if (SCM_UNBNDP (port))
1737 port = scm_current_input_port ();
1738 SCM_VALIDATE_OPINPORT (1, port);
1739 c = scm_getc_unlocked (port);
1740 if (EOF == c)
1741 return SCM_EOF_VAL;
1742 return SCM_MAKE_CHAR (c);
1743 }
1744 #undef FUNC_NAME
1745
1746
1747 \f
1748
1749 /* Pushback. */
1750
1751 void
1752 scm_unget_byte_unlocked (int c, SCM port)
1753 #define FUNC_NAME "scm_unget_byte"
1754 {
1755 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1756
1757 if (pt->read_buf == pt->putback_buf)
1758 /* already using the put-back buffer. */
1759 {
1760 /* enlarge putback_buf if necessary. */
1761 if (pt->read_end == pt->read_buf + pt->read_buf_size
1762 && pt->read_buf == pt->read_pos)
1763 {
1764 size_t new_size = pt->read_buf_size * 2;
1765 unsigned char *tmp = (unsigned char *)
1766 scm_gc_realloc (pt->putback_buf, pt->read_buf_size, new_size,
1767 "putback buffer");
1768
1769 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
1770 pt->read_end = pt->read_buf + pt->read_buf_size;
1771 pt->read_buf_size = pt->putback_buf_size = new_size;
1772 }
1773
1774 /* shift any existing bytes to buffer + 1. */
1775 if (pt->read_pos == pt->read_end)
1776 pt->read_end = pt->read_buf + 1;
1777 else if (pt->read_pos != pt->read_buf + 1)
1778 {
1779 int count = pt->read_end - pt->read_pos;
1780
1781 memmove (pt->read_buf + 1, pt->read_pos, count);
1782 pt->read_end = pt->read_buf + 1 + count;
1783 }
1784
1785 pt->read_pos = pt->read_buf;
1786 }
1787 else
1788 /* switch to the put-back buffer. */
1789 {
1790 if (pt->putback_buf == NULL)
1791 {
1792 pt->putback_buf
1793 = (unsigned char *) scm_gc_malloc_pointerless
1794 (SCM_INITIAL_PUTBACK_BUF_SIZE, "putback buffer");
1795 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
1796 }
1797
1798 pt->saved_read_buf = pt->read_buf;
1799 pt->saved_read_pos = pt->read_pos;
1800 pt->saved_read_end = pt->read_end;
1801 pt->saved_read_buf_size = pt->read_buf_size;
1802
1803 pt->read_pos = pt->read_buf = pt->putback_buf;
1804 pt->read_end = pt->read_buf + 1;
1805 pt->read_buf_size = pt->putback_buf_size;
1806 }
1807
1808 *pt->read_buf = c;
1809
1810 if (pt->rw_random)
1811 pt->rw_active = SCM_PORT_READ;
1812 }
1813 #undef FUNC_NAME
1814
1815 void
1816 scm_unget_byte (int c, SCM port)
1817 {
1818 scm_i_pthread_mutex_t *lock;
1819 scm_c_lock_port (port, &lock);
1820 scm_unget_byte_unlocked (c, port);
1821 if (lock)
1822 scm_i_pthread_mutex_unlock (lock);
1823
1824 }
1825
1826 void
1827 scm_ungetc_unlocked (scm_t_wchar c, SCM port)
1828 #define FUNC_NAME "scm_ungetc"
1829 {
1830 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1831 char *result;
1832 char result_buf[10];
1833 const char *encoding;
1834 size_t len;
1835 int i;
1836
1837 if (pt->encoding != NULL)
1838 encoding = pt->encoding;
1839 else
1840 encoding = "ISO-8859-1";
1841
1842 len = sizeof (result_buf);
1843 scm_i_lock_iconv ();
1844 result = u32_conv_to_encoding (encoding,
1845 (enum iconv_ilseq_handler) pt->ilseq_handler,
1846 (uint32_t *) &c, 1, NULL,
1847 result_buf, &len);
1848 scm_i_unlock_iconv ();
1849
1850 if (SCM_UNLIKELY (result == NULL || len == 0))
1851 scm_encoding_error (FUNC_NAME, errno,
1852 "conversion to port encoding failed",
1853 SCM_BOOL_F, SCM_MAKE_CHAR (c));
1854
1855 for (i = len - 1; i >= 0; i--)
1856 scm_unget_byte_unlocked (result[i], port);
1857
1858 if (SCM_UNLIKELY (result != result_buf))
1859 free (result);
1860
1861 if (c == '\n')
1862 {
1863 /* What should col be in this case?
1864 * We'll leave it at -1.
1865 */
1866 SCM_LINUM (port) -= 1;
1867 }
1868 else
1869 SCM_COL(port) -= 1;
1870 }
1871 #undef FUNC_NAME
1872
1873 void
1874 scm_ungetc (scm_t_wchar c, SCM port)
1875 {
1876 scm_i_pthread_mutex_t *lock;
1877 scm_c_lock_port (port, &lock);
1878 scm_ungetc_unlocked (c, port);
1879 if (lock)
1880 scm_i_pthread_mutex_unlock (lock);
1881
1882 }
1883
1884 void
1885 scm_ungets_unlocked (const char *s, int n, SCM port)
1886 {
1887 /* This is simple minded and inefficient, but unreading strings is
1888 * probably not a common operation, and remember that line and
1889 * column numbers have to be handled...
1890 *
1891 * Please feel free to write an optimized version!
1892 */
1893 while (n--)
1894 scm_ungetc_unlocked (s[n], port);
1895 }
1896
1897 void
1898 scm_ungets (const char *s, int n, SCM port)
1899 {
1900 scm_i_pthread_mutex_t *lock;
1901 scm_c_lock_port (port, &lock);
1902 scm_ungets_unlocked (s, n, port);
1903 if (lock)
1904 scm_i_pthread_mutex_unlock (lock);
1905
1906 }
1907
1908 SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1909 (SCM port),
1910 "Return the next character available from @var{port},\n"
1911 "@emph{without} updating @var{port} to point to the following\n"
1912 "character. If no more characters are available, the\n"
1913 "end-of-file object is returned.\n"
1914 "\n"
1915 "The value returned by\n"
1916 "a call to @code{peek-char} is the same as the value that would\n"
1917 "have been returned by a call to @code{read-char} on the same\n"
1918 "port. The only difference is that the very next call to\n"
1919 "@code{read-char} or @code{peek-char} on that @var{port} will\n"
1920 "return the value returned by the preceding call to\n"
1921 "@code{peek-char}. In particular, a call to @code{peek-char} on\n"
1922 "an interactive port will hang waiting for input whenever a call\n"
1923 "to @code{read-char} would have hung.\n"
1924 "\n"
1925 "As for @code{read-char}, a @code{decoding-error} may be raised\n"
1926 "if such a situation occurs. However, unlike with @code{read-char},\n"
1927 "@var{port} still points at the beginning of the erroneous byte\n"
1928 "sequence when the error is raised.\n")
1929 #define FUNC_NAME s_scm_peek_char
1930 {
1931 int err;
1932 SCM result;
1933 scm_t_wchar c;
1934 char bytes[SCM_MBCHAR_BUF_SIZE];
1935 long column, line, i;
1936 size_t len;
1937
1938 if (SCM_UNBNDP (port))
1939 port = scm_current_input_port ();
1940 SCM_VALIDATE_OPINPORT (1, port);
1941
1942 column = SCM_COL (port);
1943 line = SCM_LINUM (port);
1944
1945 err = get_codepoint (port, &c, bytes, &len);
1946
1947 for (i = len - 1; i >= 0; i--)
1948 scm_unget_byte_unlocked (bytes[i], port);
1949
1950 SCM_COL (port) = column;
1951 SCM_LINUM (port) = line;
1952
1953 if (SCM_UNLIKELY (err != 0))
1954 {
1955 scm_decoding_error (FUNC_NAME, err, "input decoding error", port);
1956
1957 /* Shouldn't happen since `catch' always aborts to prompt. */
1958 result = SCM_BOOL_F;
1959 }
1960 else if (c == EOF)
1961 result = SCM_EOF_VAL;
1962 else
1963 result = SCM_MAKE_CHAR (c);
1964
1965 return result;
1966 }
1967 #undef FUNC_NAME
1968
1969 SCM_DEFINE (scm_unread_char, "unread-char", 1, 1, 0,
1970 (SCM cobj, SCM port),
1971 "Place character @var{cobj} in @var{port} so that it will be\n"
1972 "read by the next read operation. If called multiple times, the\n"
1973 "unread characters will be read again in last-in first-out\n"
1974 "order. If @var{port} is not supplied, the current input port\n"
1975 "is used.")
1976 #define FUNC_NAME s_scm_unread_char
1977 {
1978 int c;
1979
1980 SCM_VALIDATE_CHAR (1, cobj);
1981 if (SCM_UNBNDP (port))
1982 port = scm_current_input_port ();
1983 SCM_VALIDATE_OPINPORT (2, port);
1984
1985 c = SCM_CHAR (cobj);
1986
1987 scm_ungetc_unlocked (c, port);
1988 return cobj;
1989 }
1990 #undef FUNC_NAME
1991
1992 SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1993 (SCM str, SCM port),
1994 "Place the string @var{str} in @var{port} so that its characters will be\n"
1995 "read in subsequent read operations. If called multiple times, the\n"
1996 "unread characters will be read again in last-in first-out order. If\n"
1997 "@var{port} is not supplied, the current-input-port is used.")
1998 #define FUNC_NAME s_scm_unread_string
1999 {
2000 int n;
2001 SCM_VALIDATE_STRING (1, str);
2002 if (SCM_UNBNDP (port))
2003 port = scm_current_input_port ();
2004 SCM_VALIDATE_OPINPORT (2, port);
2005
2006 n = scm_i_string_length (str);
2007
2008 while (n--)
2009 scm_ungetc_unlocked (scm_i_string_ref (str, n), port);
2010
2011 return str;
2012 }
2013 #undef FUNC_NAME
2014
2015
2016 \f
2017
2018 /* Manipulating the buffers. */
2019
2020 /* This routine does not take any locks, as it is usually called as part
2021 of a port implementation. */
2022 void
2023 scm_port_non_buffer (scm_t_port *pt)
2024 {
2025 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
2026 pt->write_buf = pt->write_pos = &pt->shortbuf;
2027 pt->read_buf_size = pt->write_buf_size = 1;
2028 pt->write_end = pt->write_buf + pt->write_buf_size;
2029 }
2030
2031 /* this should only be called when the read buffer is empty. it
2032 tries to refill the read buffer. it returns the first char from
2033 the port, which is either EOF or *(pt->read_pos). */
2034 int
2035 scm_fill_input_unlocked (SCM port)
2036 {
2037 scm_t_port *pt = SCM_PTAB_ENTRY (port);
2038
2039 assert (pt->read_pos == pt->read_end);
2040
2041 if (pt->read_buf == pt->putback_buf)
2042 {
2043 /* finished reading put-back chars. */
2044 pt->read_buf = pt->saved_read_buf;
2045 pt->read_pos = pt->saved_read_pos;
2046 pt->read_end = pt->saved_read_end;
2047 pt->read_buf_size = pt->saved_read_buf_size;
2048 if (pt->read_pos < pt->read_end)
2049 return *(pt->read_pos);
2050 }
2051 return SCM_PORT_DESCRIPTOR (port)->fill_input (port);
2052 }
2053
2054 int
2055 scm_fill_input (SCM port)
2056 {
2057 scm_i_pthread_mutex_t *lock;
2058 int ret;
2059
2060 scm_c_lock_port (port, &lock);
2061 ret = scm_fill_input_unlocked (port);
2062 if (lock)
2063 scm_i_pthread_mutex_unlock (lock);
2064
2065
2066 return ret;
2067 }
2068
2069 /* move up to read_len chars from port's putback and/or read buffers
2070 into memory starting at dest. returns the number of chars moved. */
2071 size_t
2072 scm_take_from_input_buffers (SCM port, char *dest, size_t read_len)
2073 {
2074 scm_t_port *pt = SCM_PTAB_ENTRY (port);
2075 size_t chars_read = 0;
2076 size_t from_buf = min (pt->read_end - pt->read_pos, read_len);
2077
2078 if (from_buf > 0)
2079 {
2080 memcpy (dest, pt->read_pos, from_buf);
2081 pt->read_pos += from_buf;
2082 chars_read += from_buf;
2083 read_len -= from_buf;
2084 dest += from_buf;
2085 }
2086
2087 /* if putback was active, try the real input buffer too. */
2088 if (pt->read_buf == pt->putback_buf)
2089 {
2090 from_buf = min (pt->saved_read_end - pt->saved_read_pos, read_len);
2091 if (from_buf > 0)
2092 {
2093 memcpy (dest, pt->saved_read_pos, from_buf);
2094 pt->saved_read_pos += from_buf;
2095 chars_read += from_buf;
2096 }
2097 }
2098 return chars_read;
2099 }
2100
2101 /* Clear a port's read buffers, returning the contents. */
2102 SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
2103 (SCM port),
2104 "This procedure clears a port's input buffers, similar\n"
2105 "to the way that force-output clears the output buffer. The\n"
2106 "contents of the buffers are returned as a single string, e.g.,\n"
2107 "\n"
2108 "@lisp\n"
2109 "(define p (open-input-file ...))\n"
2110 "(drain-input p) => empty string, nothing buffered yet.\n"
2111 "(unread-char (read-char p) p)\n"
2112 "(drain-input p) => initial chars from p, up to the buffer size.\n"
2113 "@end lisp\n\n"
2114 "Draining the buffers may be useful for cleanly finishing\n"
2115 "buffered I/O so that the file descriptor can be used directly\n"
2116 "for further input.")
2117 #define FUNC_NAME s_scm_drain_input
2118 {
2119 SCM result;
2120 char *data;
2121 scm_t_port *pt;
2122 long count;
2123
2124 SCM_VALIDATE_OPINPORT (1, port);
2125 pt = SCM_PTAB_ENTRY (port);
2126
2127 count = pt->read_end - pt->read_pos;
2128 if (pt->read_buf == pt->putback_buf)
2129 count += pt->saved_read_end - pt->saved_read_pos;
2130
2131 if (count)
2132 {
2133 result = scm_i_make_string (count, &data, 0);
2134 scm_take_from_input_buffers (port, data, count);
2135 }
2136 else
2137 result = scm_nullstr;
2138
2139 return result;
2140 }
2141 #undef FUNC_NAME
2142
2143 void
2144 scm_end_input_unlocked (SCM port)
2145 {
2146 long offset;
2147 scm_t_port *pt = SCM_PTAB_ENTRY (port);
2148
2149 if (pt->read_buf == pt->putback_buf)
2150 {
2151 offset = pt->read_end - pt->read_pos;
2152 pt->read_buf = pt->saved_read_buf;
2153 pt->read_pos = pt->saved_read_pos;
2154 pt->read_end = pt->saved_read_end;
2155 pt->read_buf_size = pt->saved_read_buf_size;
2156 }
2157 else
2158 offset = 0;
2159
2160 SCM_PORT_DESCRIPTOR (port)->end_input (port, offset);
2161 }
2162
2163 void
2164 scm_end_input (SCM port)
2165 {
2166 scm_i_pthread_mutex_t *lock;
2167 scm_c_lock_port (port, &lock);
2168 scm_end_input_unlocked (port);
2169 if (lock)
2170 scm_i_pthread_mutex_unlock (lock);
2171
2172 }
2173
2174 SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
2175 (SCM port),
2176 "Flush the specified output port, or the current output port if @var{port}\n"
2177 "is omitted. The current output buffer contents are passed to the\n"
2178 "underlying port implementation (e.g., in the case of fports, the\n"
2179 "data will be written to the file and the output buffer will be cleared.)\n"
2180 "It has no effect on an unbuffered port.\n\n"
2181 "The return value is unspecified.")
2182 #define FUNC_NAME s_scm_force_output
2183 {
2184 if (SCM_UNBNDP (port))
2185 port = scm_current_output_port ();
2186 else
2187 {
2188 port = SCM_COERCE_OUTPORT (port);
2189 SCM_VALIDATE_OPOUTPORT (1, port);
2190 }
2191 scm_flush_unlocked (port);
2192 return SCM_UNSPECIFIED;
2193 }
2194 #undef FUNC_NAME
2195
2196 void
2197 scm_flush_unlocked (SCM port)
2198 {
2199 SCM_PORT_DESCRIPTOR (port)->flush (port);
2200 }
2201
2202 void
2203 scm_flush (SCM port)
2204 {
2205 scm_i_pthread_mutex_t *lock;
2206 scm_c_lock_port (port, &lock);
2207 scm_flush_unlocked (port);
2208 if (lock)
2209 scm_i_pthread_mutex_unlock (lock);
2210
2211 }
2212
2213
2214 \f
2215
2216 /* Output. */
2217
2218 void
2219 scm_putc (char c, SCM port)
2220 {
2221 scm_i_pthread_mutex_t *lock;
2222 scm_c_lock_port (port, &lock);
2223 scm_putc_unlocked (c, port);
2224 if (lock)
2225 scm_i_pthread_mutex_unlock (lock);
2226
2227 }
2228
2229 void
2230 scm_puts (const char *s, SCM port)
2231 {
2232 scm_i_pthread_mutex_t *lock;
2233 scm_c_lock_port (port, &lock);
2234 scm_puts_unlocked (s, port);
2235 if (lock)
2236 scm_i_pthread_mutex_unlock (lock);
2237
2238 }
2239
2240 /* scm_c_write
2241 *
2242 * Used by an application to write arbitrary number of bytes to an SCM
2243 * port. Similar semantics as libc write. However, unlike libc
2244 * write, scm_c_write writes the requested number of bytes and has no
2245 * return value.
2246 *
2247 * Warning: Doesn't update port line and column counts!
2248 */
2249 void
2250 scm_c_write_unlocked (SCM port, const void *ptr, size_t size)
2251 #define FUNC_NAME "scm_c_write"
2252 {
2253 scm_t_port *pt;
2254 scm_t_ptob_descriptor *ptob;
2255
2256 SCM_VALIDATE_OPOUTPORT (1, port);
2257
2258 pt = SCM_PTAB_ENTRY (port);
2259 ptob = SCM_PORT_DESCRIPTOR (port);
2260
2261 if (pt->rw_active == SCM_PORT_READ)
2262 scm_end_input_unlocked (port);
2263
2264 ptob->write (port, ptr, size);
2265
2266 if (pt->rw_random)
2267 pt->rw_active = SCM_PORT_WRITE;
2268 }
2269 #undef FUNC_NAME
2270
2271 void
2272 scm_c_write (SCM port, const void *ptr, size_t size)
2273 {
2274 scm_i_pthread_mutex_t *lock;
2275 scm_c_lock_port (port, &lock);
2276 scm_c_write_unlocked (port, ptr, size);
2277 if (lock)
2278 scm_i_pthread_mutex_unlock (lock);
2279
2280 }
2281
2282 /* scm_lfwrite
2283 *
2284 * This function differs from scm_c_write; it updates port line and
2285 * column. */
2286 void
2287 scm_lfwrite_unlocked (const char *ptr, size_t size, SCM port)
2288 {
2289 scm_t_port *pt = SCM_PTAB_ENTRY (port);
2290 scm_t_ptob_descriptor *ptob = SCM_PORT_DESCRIPTOR (port);
2291
2292 if (pt->rw_active == SCM_PORT_READ)
2293 scm_end_input_unlocked (port);
2294
2295 ptob->write (port, ptr, size);
2296
2297 for (; size; ptr++, size--)
2298 update_port_lf ((scm_t_wchar) (unsigned char) *ptr, port);
2299
2300 if (pt->rw_random)
2301 pt->rw_active = SCM_PORT_WRITE;
2302 }
2303
2304 void
2305 scm_lfwrite (const char *ptr, size_t size, SCM port)
2306 {
2307 scm_i_pthread_mutex_t *lock;
2308 scm_c_lock_port (port, &lock);
2309 scm_lfwrite_unlocked (ptr, size, port);
2310 if (lock)
2311 scm_i_pthread_mutex_unlock (lock);
2312
2313 }
2314
2315 /* Write STR to PORT from START inclusive to END exclusive. */
2316 void
2317 scm_lfwrite_substr (SCM str, size_t start, size_t end, SCM port)
2318 {
2319 scm_t_port *pt = SCM_PTAB_ENTRY (port);
2320
2321 if (pt->rw_active == SCM_PORT_READ)
2322 scm_end_input_unlocked (port);
2323
2324 if (end == (size_t) -1)
2325 end = scm_i_string_length (str);
2326
2327 scm_display (scm_c_substring (str, start, end), port);
2328
2329 if (pt->rw_random)
2330 pt->rw_active = SCM_PORT_WRITE;
2331 }
2332
2333
2334 \f
2335
2336 /* Querying and setting positions, and character availability. */
2337
2338 SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
2339 (SCM port),
2340 "Return @code{#t} if a character is ready on input @var{port}\n"
2341 "and return @code{#f} otherwise. If @code{char-ready?} returns\n"
2342 "@code{#t} then the next @code{read-char} operation on\n"
2343 "@var{port} is guaranteed not to hang. If @var{port} is a file\n"
2344 "port at end of file then @code{char-ready?} returns @code{#t}.\n"
2345 "\n"
2346 "@code{char-ready?} exists to make it possible for a\n"
2347 "program to accept characters from interactive ports without\n"
2348 "getting stuck waiting for input. Any input editors associated\n"
2349 "with such ports must make sure that characters whose existence\n"
2350 "has been asserted by @code{char-ready?} cannot be rubbed out.\n"
2351 "If @code{char-ready?} were to return @code{#f} at end of file,\n"
2352 "a port at end of file would be indistinguishable from an\n"
2353 "interactive port that has no ready characters.")
2354 #define FUNC_NAME s_scm_char_ready_p
2355 {
2356 scm_t_port *pt;
2357
2358 if (SCM_UNBNDP (port))
2359 port = scm_current_input_port ();
2360 /* It's possible to close the current input port, so validate even in
2361 this case. */
2362 SCM_VALIDATE_OPINPORT (1, port);
2363
2364 pt = SCM_PTAB_ENTRY (port);
2365
2366 /* if the current read buffer is filled, or the
2367 last pushed-back char has been read and the saved buffer is
2368 filled, result is true. */
2369 if (pt->read_pos < pt->read_end
2370 || (pt->read_buf == pt->putback_buf
2371 && pt->saved_read_pos < pt->saved_read_end))
2372 return SCM_BOOL_T;
2373 else
2374 {
2375 scm_t_ptob_descriptor *ptob = SCM_PORT_DESCRIPTOR (port);
2376
2377 if (ptob->input_waiting)
2378 return scm_from_bool(ptob->input_waiting (port));
2379 else
2380 return SCM_BOOL_T;
2381 }
2382 }
2383 #undef FUNC_NAME
2384
2385 SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
2386 (SCM fd_port, SCM offset, SCM whence),
2387 "Sets the current position of @var{fd_port} to the integer\n"
2388 "@var{offset}, which is interpreted according to the value of\n"
2389 "@var{whence}.\n"
2390 "\n"
2391 "One of the following variables should be supplied for\n"
2392 "@var{whence}:\n"
2393 "@defvar SEEK_SET\n"
2394 "Seek from the beginning of the file.\n"
2395 "@end defvar\n"
2396 "@defvar SEEK_CUR\n"
2397 "Seek from the current position.\n"
2398 "@end defvar\n"
2399 "@defvar SEEK_END\n"
2400 "Seek from the end of the file.\n"
2401 "@end defvar\n"
2402 "If @var{fd_port} is a file descriptor, the underlying system\n"
2403 "call is @code{lseek}. @var{port} may be a string port.\n"
2404 "\n"
2405 "The value returned is the new position in the file. This means\n"
2406 "that the current position of a port can be obtained using:\n"
2407 "@lisp\n"
2408 "(seek port 0 SEEK_CUR)\n"
2409 "@end lisp")
2410 #define FUNC_NAME s_scm_seek
2411 {
2412 int how;
2413
2414 fd_port = SCM_COERCE_OUTPORT (fd_port);
2415
2416 how = scm_to_int (whence);
2417 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
2418 SCM_OUT_OF_RANGE (3, whence);
2419
2420 if (SCM_OPPORTP (fd_port))
2421 {
2422 scm_t_ptob_descriptor *ptob = SCM_PORT_DESCRIPTOR (fd_port);
2423 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
2424 off_t_or_off64_t rv;
2425
2426 if (!ptob->seek)
2427 SCM_MISC_ERROR ("port is not seekable",
2428 scm_cons (fd_port, SCM_EOL));
2429 else
2430 rv = ptob->seek (fd_port, off, how);
2431 return scm_from_off_t_or_off64_t (rv);
2432 }
2433 else /* file descriptor?. */
2434 {
2435 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
2436 off_t_or_off64_t rv;
2437 rv = lseek_or_lseek64 (scm_to_int (fd_port), off, how);
2438 if (rv == -1)
2439 SCM_SYSERROR;
2440 return scm_from_off_t_or_off64_t (rv);
2441 }
2442 }
2443 #undef FUNC_NAME
2444
2445 #ifndef O_BINARY
2446 #define O_BINARY 0
2447 #endif
2448
2449 /* Mingw has ftruncate(), perhaps implemented above using chsize, but
2450 doesn't have the filename version truncate(), hence this code. */
2451 #if HAVE_FTRUNCATE && ! HAVE_TRUNCATE
2452 static int
2453 truncate (const char *file, off_t length)
2454 {
2455 int ret, fdes;
2456
2457 fdes = open (file, O_BINARY | O_WRONLY);
2458 if (fdes == -1)
2459 return -1;
2460
2461 ret = ftruncate (fdes, length);
2462 if (ret == -1)
2463 {
2464 int save_errno = errno;
2465 close (fdes);
2466 errno = save_errno;
2467 return -1;
2468 }
2469
2470 return close (fdes);
2471 }
2472 #endif /* HAVE_FTRUNCATE && ! HAVE_TRUNCATE */
2473
2474 SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
2475 (SCM object, SCM length),
2476 "Truncate file @var{object} to @var{length} bytes. @var{object}\n"
2477 "can be a filename string, a port object, or an integer file\n"
2478 "descriptor.\n"
2479 "The return value is unspecified.\n"
2480 "\n"
2481 "For a port or file descriptor @var{length} can be omitted, in\n"
2482 "which case the file is truncated at the current position (per\n"
2483 "@code{ftell} above).\n"
2484 "\n"
2485 "On most systems a file can be extended by giving a length\n"
2486 "greater than the current size, but this is not mandatory in the\n"
2487 "POSIX standard.")
2488 #define FUNC_NAME s_scm_truncate_file
2489 {
2490 int rv;
2491
2492 /* "object" can be a port, fdes or filename.
2493
2494 Negative "length" makes no sense, but it's left to truncate() or
2495 ftruncate() to give back an error for that (normally EINVAL).
2496 */
2497
2498 if (SCM_UNBNDP (length))
2499 {
2500 /* must supply length if object is a filename. */
2501 if (scm_is_string (object))
2502 SCM_MISC_ERROR("must supply length if OBJECT is a filename", SCM_EOL);
2503
2504 length = scm_seek (object, SCM_INUM0, scm_from_int (SEEK_CUR));
2505 }
2506
2507 object = SCM_COERCE_OUTPORT (object);
2508 if (scm_is_integer (object))
2509 {
2510 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
2511 SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
2512 c_length));
2513 }
2514 else if (SCM_OPOUTPORTP (object))
2515 {
2516 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
2517 scm_t_port *pt = SCM_PTAB_ENTRY (object);
2518 scm_t_ptob_descriptor *ptob = SCM_PORT_DESCRIPTOR (object);
2519
2520 if (!ptob->truncate)
2521 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
2522 if (pt->rw_active == SCM_PORT_READ)
2523 scm_end_input_unlocked (object);
2524 else if (pt->rw_active == SCM_PORT_WRITE)
2525 ptob->flush (object);
2526
2527 ptob->truncate (object, c_length);
2528 rv = 0;
2529 }
2530 else
2531 {
2532 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
2533 char *str = scm_to_locale_string (object);
2534 int eno;
2535 SCM_SYSCALL (rv = truncate_or_truncate64 (str, c_length));
2536 eno = errno;
2537 free (str);
2538 errno = eno;
2539 }
2540 if (rv == -1)
2541 SCM_SYSERROR;
2542 return SCM_UNSPECIFIED;
2543 }
2544 #undef FUNC_NAME
2545
2546 SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
2547 (SCM port),
2548 "Return the current line number for @var{port}.\n"
2549 "\n"
2550 "The first line of a file is 0. But you might want to add 1\n"
2551 "when printing line numbers, since starting from 1 is\n"
2552 "traditional in error messages, and likely to be more natural to\n"
2553 "non-programmers.")
2554 #define FUNC_NAME s_scm_port_line
2555 {
2556 port = SCM_COERCE_OUTPORT (port);
2557 SCM_VALIDATE_OPENPORT (1, port);
2558 return scm_from_long (SCM_LINUM (port));
2559 }
2560 #undef FUNC_NAME
2561
2562 SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
2563 (SCM port, SCM line),
2564 "Set the current line number for @var{port} to @var{line}. The\n"
2565 "first line of a file is 0.")
2566 #define FUNC_NAME s_scm_set_port_line_x
2567 {
2568 port = SCM_COERCE_OUTPORT (port);
2569 SCM_VALIDATE_OPENPORT (1, port);
2570 SCM_PTAB_ENTRY (port)->line_number = scm_to_long (line);
2571 return SCM_UNSPECIFIED;
2572 }
2573 #undef FUNC_NAME
2574
2575 SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
2576 (SCM port),
2577 "Return the current column number of @var{port}.\n"
2578 "If the number is\n"
2579 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
2580 "- i.e. the first character of the first line is line 0, column 0.\n"
2581 "(However, when you display a file position, for example in an error\n"
2582 "message, we recommend you add 1 to get 1-origin integers. This is\n"
2583 "because lines and column numbers traditionally start with 1, and that is\n"
2584 "what non-programmers will find most natural.)")
2585 #define FUNC_NAME s_scm_port_column
2586 {
2587 port = SCM_COERCE_OUTPORT (port);
2588 SCM_VALIDATE_OPENPORT (1, port);
2589 return scm_from_int (SCM_COL (port));
2590 }
2591 #undef FUNC_NAME
2592
2593 SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
2594 (SCM port, SCM column),
2595 "Set the current column of @var{port}. Before reading the first\n"
2596 "character on a line the column should be 0.")
2597 #define FUNC_NAME s_scm_set_port_column_x
2598 {
2599 port = SCM_COERCE_OUTPORT (port);
2600 SCM_VALIDATE_OPENPORT (1, port);
2601 SCM_PTAB_ENTRY (port)->column_number = scm_to_int (column);
2602 return SCM_UNSPECIFIED;
2603 }
2604 #undef FUNC_NAME
2605
2606 SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
2607 (SCM port),
2608 "Return the filename associated with @var{port}, or @code{#f}\n"
2609 "if no filename is associated with the port.")
2610 #define FUNC_NAME s_scm_port_filename
2611 {
2612 port = SCM_COERCE_OUTPORT (port);
2613 SCM_VALIDATE_OPENPORT (1, port);
2614 return SCM_FILENAME (port);
2615 }
2616 #undef FUNC_NAME
2617
2618 SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
2619 (SCM port, SCM filename),
2620 "Change the filename associated with @var{port}, using the current input\n"
2621 "port if none is specified. Note that this does not change the port's\n"
2622 "source of data, but only the value that is returned by\n"
2623 "@code{port-filename} and reported in diagnostic output.")
2624 #define FUNC_NAME s_scm_set_port_filename_x
2625 {
2626 port = SCM_COERCE_OUTPORT (port);
2627 SCM_VALIDATE_OPENPORT (1, port);
2628 /* We allow the user to set the filename to whatever he likes. */
2629 SCM_SET_FILENAME (port, filename);
2630 return SCM_UNSPECIFIED;
2631 }
2632 #undef FUNC_NAME
2633
2634
2635 \f
2636
2637 /* Implementation helpers for port printing functions. */
2638
2639 void
2640 scm_print_port_mode (SCM exp, SCM port)
2641 {
2642 scm_puts_unlocked (SCM_CLOSEDP (exp)
2643 ? "closed: "
2644 : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
2645 ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
2646 ? "input-output: "
2647 : "input: ")
2648 : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
2649 ? "output: "
2650 : "bogus: ")),
2651 port);
2652 }
2653
2654 int
2655 scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
2656 {
2657 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
2658 if (!type)
2659 type = "port";
2660 scm_puts_unlocked ("#<", port);
2661 scm_print_port_mode (exp, port);
2662 scm_puts_unlocked (type, port);
2663 scm_putc_unlocked (' ', port);
2664 scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
2665 scm_putc_unlocked ('>', port);
2666 return 1;
2667 }
2668
2669
2670 \f
2671
2672 /* Iterating over all ports. */
2673
2674 struct for_each_data
2675 {
2676 void (*proc) (void *data, SCM p);
2677 void *data;
2678 };
2679
2680 static SCM
2681 for_each_trampoline (void *data, SCM port, SCM result)
2682 {
2683 struct for_each_data *d = data;
2684
2685 d->proc (d->data, port);
2686
2687 return result;
2688 }
2689
2690 void
2691 scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
2692 {
2693 struct for_each_data d;
2694
2695 d.proc = proc;
2696 d.data = data;
2697
2698 scm_c_weak_set_fold (for_each_trampoline, &d, SCM_EOL,
2699 scm_i_port_weak_set);
2700 }
2701
2702 static void
2703 scm_for_each_trampoline (void *data, SCM port)
2704 {
2705 scm_call_1 (SCM_PACK_POINTER (data), port);
2706 }
2707
2708 SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
2709 (SCM proc),
2710 "Apply @var{proc} to each port in the Guile port table\n"
2711 "in turn. The return value is unspecified. More specifically,\n"
2712 "@var{proc} is applied exactly once to every port that exists\n"
2713 "in the system at the time @code{port-for-each} is invoked.\n"
2714 "Changes to the port table while @code{port-for-each} is running\n"
2715 "have no effect as far as @code{port-for-each} is concerned.")
2716 #define FUNC_NAME s_scm_port_for_each
2717 {
2718 SCM_VALIDATE_PROC (1, proc);
2719
2720 scm_c_port_for_each (scm_for_each_trampoline, SCM_UNPACK_POINTER (proc));
2721
2722 return SCM_UNSPECIFIED;
2723 }
2724 #undef FUNC_NAME
2725
2726 static void
2727 flush_output_port (void *closure, SCM port)
2728 {
2729 if (SCM_OPOUTPORTP (port))
2730 scm_flush_unlocked (port);
2731 }
2732
2733 SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
2734 (),
2735 "Equivalent to calling @code{force-output} on\n"
2736 "all open output ports. The return value is unspecified.")
2737 #define FUNC_NAME s_scm_flush_all_ports
2738 {
2739 scm_c_port_for_each (&flush_output_port, NULL);
2740 return SCM_UNSPECIFIED;
2741 }
2742 #undef FUNC_NAME
2743
2744
2745 \f
2746
2747 /* Void ports. */
2748
2749 scm_t_bits scm_tc16_void_port = 0;
2750
2751 static int fill_input_void_port (SCM port SCM_UNUSED)
2752 {
2753 return EOF;
2754 }
2755
2756 static void
2757 write_void_port (SCM port SCM_UNUSED,
2758 const void *data SCM_UNUSED,
2759 size_t size SCM_UNUSED)
2760 {
2761 }
2762
2763 static SCM
2764 scm_i_void_port (long mode_bits)
2765 {
2766 SCM ret;
2767
2768 ret = scm_c_make_port (scm_tc16_void_port, mode_bits, 0);
2769
2770 scm_port_non_buffer (SCM_PTAB_ENTRY (ret));
2771
2772 return ret;
2773 }
2774
2775 SCM
2776 scm_void_port (char *mode_str)
2777 {
2778 return scm_i_void_port (scm_mode_bits (mode_str));
2779 }
2780
2781 SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
2782 (SCM mode),
2783 "Create and return a new void port. A void port acts like\n"
2784 "@file{/dev/null}. The @var{mode} argument\n"
2785 "specifies the input/output modes for this port: see the\n"
2786 "documentation for @code{open-file} in @ref{File Ports}.")
2787 #define FUNC_NAME s_scm_sys_make_void_port
2788 {
2789 return scm_i_void_port (scm_i_mode_bits (mode));
2790 }
2791 #undef FUNC_NAME
2792
2793
2794 \f
2795
2796 /* Initialization. */
2797
2798 void
2799 scm_init_ports ()
2800 {
2801 /* lseek() symbols. */
2802 scm_c_define ("SEEK_SET", scm_from_int (SEEK_SET));
2803 scm_c_define ("SEEK_CUR", scm_from_int (SEEK_CUR));
2804 scm_c_define ("SEEK_END", scm_from_int (SEEK_END));
2805
2806 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
2807 write_void_port);
2808
2809 cur_inport_fluid = scm_make_fluid ();
2810 cur_outport_fluid = scm_make_fluid ();
2811 cur_errport_fluid = scm_make_fluid ();
2812 cur_loadport_fluid = scm_make_fluid ();
2813
2814 scm_i_port_weak_set = scm_c_make_weak_set (31);
2815
2816 #include "libguile/ports.x"
2817
2818 /* Use Latin-1 as the default port encoding. */
2819 SCM_VARIABLE_SET (default_port_encoding_var,
2820 scm_make_fluid_with_default (SCM_BOOL_F));
2821 scm_port_encoding_init = 1;
2822
2823 SCM_VARIABLE_SET (scm_conversion_strategy,
2824 scm_make_fluid_with_default
2825 (scm_from_int ((int) SCM_FAILED_CONVERSION_QUESTION_MARK)));
2826 scm_conversion_strategy_init = 1;
2827
2828 /* These bindings are used when boot-9 turns `current-input-port' et
2829 al into parameters. They are then removed from the guile module. */
2830 scm_c_define ("%current-input-port-fluid", cur_inport_fluid);
2831 scm_c_define ("%current-output-port-fluid", cur_outport_fluid);
2832 scm_c_define ("%current-error-port-fluid", cur_errport_fluid);
2833 }
2834
2835 /*
2836 Local Variables:
2837 c-file-style: "gnu"
2838 End:
2839 */