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