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