optimize scm_from_latin1_symboln
[bpt/guile.git] / libguile / ports.c
CommitLineData
0af34a3f 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
0f2d19dd 20\f
d68fee48
JB
21/* Headers. */
22
2b829bbb
KR
23#define _LARGEFILE64_SOURCE /* ask for stat64 etc */
24
dbb605f5 25#ifdef HAVE_CONFIG_H
bd515f37
RB
26# include <config.h>
27#endif
28
0f2d19dd 29#include <stdio.h>
e6e2e95a 30#include <errno.h>
8ab3d8a0 31#include <fcntl.h> /* for chsize on mingw */
b5cb4464 32#include <assert.h>
889975e5
MG
33#include <uniconv.h>
34#include <unistr.h>
35#include <striconveh.h>
e6e2e95a 36
fca43887
LC
37#include <assert.h>
38
a0599745 39#include "libguile/_scm.h"
4e047c3e 40#include "libguile/async.h"
f0942910 41#include "libguile/eval.h"
8ab3d8a0 42#include "libguile/fports.h" /* direct access for seek and truncate */
9511876f 43#include "libguile/goops.h"
a0599745
MD
44#include "libguile/smob.h"
45#include "libguile/chars.h"
185e369a 46#include "libguile/dynwind.h"
0f2d19dd 47
a0599745 48#include "libguile/keywords.h"
5dbc6c06 49#include "libguile/hashtab.h"
a0599745
MD
50#include "libguile/root.h"
51#include "libguile/strings.h"
b42170a4 52#include "libguile/mallocs.h"
a0599745
MD
53#include "libguile/validate.h"
54#include "libguile/ports.h"
3a5fb14d 55#include "libguile/vectors.h"
5dbc6c06 56#include "libguile/weaks.h"
9de87eea 57#include "libguile/fluids.h"
889975e5 58#include "libguile/eq.h"
0f2d19dd 59
bd9e24b3
GH
60#ifdef HAVE_STRING_H
61#include <string.h>
62#endif
63
ec65f5da
MV
64#ifdef HAVE_IO_H
65#include <io.h>
66#endif
67
0f2d19dd
JB
68#ifdef HAVE_UNISTD_H
69#include <unistd.h>
70#endif
71
95b88819
GH
72#ifdef HAVE_SYS_IOCTL_H
73#include <sys/ioctl.h>
74#endif
d68fee48 75
8ab3d8a0
KR
76/* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize
77 already, but have this code here in case that wasn't so in past versions,
78 or perhaps to help other minimal DOS environments.
79
80 gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which
81 might be possibilities if we've got other systems without ftruncate. */
82
56a3dcd4 83#if defined HAVE_CHSIZE && ! defined HAVE_FTRUNCATE
82893676 84#define ftruncate(fd, size) chsize (fd, size)
8ab3d8a0
KR
85#undef HAVE_FTRUNCATE
86#define HAVE_FTRUNCATE 1
82893676
MG
87#endif
88
0f2d19dd 89\f
d68fee48 90/* The port kind table --- a dynamically resized array of port types. */
0f2d19dd
JB
91
92
93/* scm_ptobs scm_numptob
5dbc6c06 94 * implement a dynamically resized array of ptob records.
0f2d19dd
JB
95 * Indexes into this table are used when generating type
96 * tags for smobjects (if you know a tag you can get an index and conversely).
97 */
dd3a26f3
AW
98scm_t_ptob_descriptor *scm_ptobs = NULL;
99long scm_numptob = 0;
0f2d19dd 100
ee149d03 101/* GC marker for a port with stream of SCM type. */
0f2d19dd 102SCM
a284e297 103scm_markstream (SCM ptr)
0f2d19dd
JB
104{
105 int openp;
f9a64404 106 openp = SCM_CELL_WORD_0 (ptr) & SCM_OPN;
0f2d19dd 107 if (openp)
74a16888 108 return SCM_PACK (SCM_STREAM (ptr));
0f2d19dd
JB
109 else
110 return SCM_BOOL_F;
111}
112
f12733c9 113/*
f12733c9 114 * We choose to use an interface similar to the smob interface with
affc96b5 115 * fill_input and write as standard fields, passed to the port
f12733c9
MD
116 * type constructor, and optional fields set by setters.
117 */
118
70df8af6 119static void
e81d98ec 120flush_port_default (SCM port SCM_UNUSED)
70df8af6
GH
121{
122}
123
124static void
e81d98ec 125end_input_default (SCM port SCM_UNUSED, int offset SCM_UNUSED)
70df8af6
GH
126{
127}
0f2d19dd 128
92c2555f 129scm_t_bits
f12733c9 130scm_make_port_type (char *name,
affc96b5 131 int (*fill_input) (SCM port),
8aa011a1 132 void (*write) (SCM port, const void *data, size_t size))
0f2d19dd
JB
133{
134 char *tmp;
0953b549 135 if (SCM_I_MAX_PORT_TYPE_COUNT - 1 <= scm_numptob)
0f2d19dd 136 goto ptoberr;
9de87eea 137 SCM_CRITICAL_SECTION_START;
fca43887
LC
138 tmp = (char *) scm_gc_realloc ((char *) scm_ptobs,
139 scm_numptob * sizeof (scm_t_ptob_descriptor),
140 (1 + scm_numptob)
141 * sizeof (scm_t_ptob_descriptor),
142 "port-type");
0f2d19dd
JB
143 if (tmp)
144 {
92c2555f 145 scm_ptobs = (scm_t_ptob_descriptor *) tmp;
affc96b5 146
f12733c9
MD
147 scm_ptobs[scm_numptob].name = name;
148 scm_ptobs[scm_numptob].mark = 0;
3051344b 149 scm_ptobs[scm_numptob].free = NULL;
f12733c9
MD
150 scm_ptobs[scm_numptob].print = scm_port_print;
151 scm_ptobs[scm_numptob].equalp = 0;
affc96b5
GH
152 scm_ptobs[scm_numptob].close = 0;
153
154 scm_ptobs[scm_numptob].write = write;
70df8af6 155 scm_ptobs[scm_numptob].flush = flush_port_default;
affc96b5 156
70df8af6 157 scm_ptobs[scm_numptob].end_input = end_input_default;
affc96b5
GH
158 scm_ptobs[scm_numptob].fill_input = fill_input;
159 scm_ptobs[scm_numptob].input_waiting = 0;
160
f12733c9 161 scm_ptobs[scm_numptob].seek = 0;
affc96b5
GH
162 scm_ptobs[scm_numptob].truncate = 0;
163
0f2d19dd
JB
164 scm_numptob++;
165 }
9de87eea 166 SCM_CRITICAL_SECTION_END;
0f2d19dd 167 if (!tmp)
2500356c
DH
168 {
169 ptoberr:
170 scm_memory_error ("scm_make_port_type");
171 }
f12733c9 172 /* Make a class object if Goops is present */
63385df2 173 if (SCM_UNPACK (scm_port_class[0]) != 0)
f12733c9 174 scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
0f2d19dd
JB
175 return scm_tc7_port + (scm_numptob - 1) * 256;
176}
177
f12733c9 178void
23f2b9a3 179scm_set_port_mark (scm_t_bits tc, SCM (*mark) (SCM))
f12733c9
MD
180{
181 scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
182}
183
184void
23f2b9a3 185scm_set_port_free (scm_t_bits tc, size_t (*free) (SCM))
f12733c9
MD
186{
187 scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
188}
189
190void
23f2b9a3 191scm_set_port_print (scm_t_bits tc, int (*print) (SCM exp, SCM port,
f12733c9
MD
192 scm_print_state *pstate))
193{
194 scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
195}
196
197void
23f2b9a3 198scm_set_port_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
f12733c9
MD
199{
200 scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
201}
202
31703ab8 203void
23f2b9a3 204scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port))
31703ab8 205{
affc96b5 206 scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
31703ab8
GH
207}
208
f12733c9 209void
23f2b9a3 210scm_set_port_end_input (scm_t_bits tc, void (*end_input) (SCM port, int offset))
f12733c9 211{
affc96b5 212 scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
f12733c9
MD
213}
214
215void
23f2b9a3 216scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
f12733c9 217{
affc96b5 218 scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
f12733c9
MD
219}
220
221void
f1ce9199
LC
222scm_set_port_seek (scm_t_bits tc,
223 scm_t_off (*seek) (SCM, scm_t_off, int))
f12733c9
MD
224{
225 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
226}
227
228void
f1ce9199 229scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM, scm_t_off))
f12733c9 230{
affc96b5 231 scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
f12733c9
MD
232}
233
234void
23f2b9a3 235scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) (SCM))
f12733c9 236{
affc96b5 237 scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
f12733c9
MD
238}
239
0f2d19dd 240\f
0f2d19dd 241
3b3b36dd 242SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
1e6808ea
MG
243 (SCM port),
244 "Return @code{#t} if a character is ready on input @var{port}\n"
245 "and return @code{#f} otherwise. If @code{char-ready?} returns\n"
246 "@code{#t} then the next @code{read-char} operation on\n"
247 "@var{port} is guaranteed not to hang. If @var{port} is a file\n"
248 "port at end of file then @code{char-ready?} returns @code{#t}.\n"
c2dfff19
KR
249 "\n"
250 "@code{char-ready?} exists to make it possible for a\n"
1e6808ea
MG
251 "program to accept characters from interactive ports without\n"
252 "getting stuck waiting for input. Any input editors associated\n"
253 "with such ports must make sure that characters whose existence\n"
254 "has been asserted by @code{char-ready?} cannot be rubbed out.\n"
255 "If @code{char-ready?} were to return @code{#f} at end of file,\n"
256 "a port at end of file would be indistinguishable from an\n"
c2dfff19 257 "interactive port that has no ready characters.")
1bbd0b84 258#define FUNC_NAME s_scm_char_ready_p
0f2d19dd 259{
92c2555f 260 scm_t_port *pt;
6c951427 261
0f2d19dd 262 if (SCM_UNBNDP (port))
9de87eea 263 port = scm_current_input_port ();
b2456dd4
AW
264 /* It's possible to close the current input port, so validate even in
265 this case. */
266 SCM_VALIDATE_OPINPORT (1, port);
d68fee48 267
ae4c4016
JB
268 pt = SCM_PTAB_ENTRY (port);
269
6c951427
GH
270 /* if the current read buffer is filled, or the
271 last pushed-back char has been read and the saved buffer is
272 filled, result is true. */
273 if (pt->read_pos < pt->read_end
274 || (pt->read_buf == pt->putback_buf
275 && pt->saved_read_pos < pt->saved_read_end))
0f2d19dd 276 return SCM_BOOL_T;
ee149d03
JB
277 else
278 {
92c2555f 279 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
ee149d03 280
affc96b5 281 if (ptob->input_waiting)
7888309b 282 return scm_from_bool(ptob->input_waiting (port));
ee149d03 283 else
6c951427 284 return SCM_BOOL_T;
ee149d03 285 }
0f2d19dd 286}
1bbd0b84 287#undef FUNC_NAME
0f2d19dd 288
c2da2648
GH
289/* move up to read_len chars from port's putback and/or read buffers
290 into memory starting at dest. returns the number of chars moved. */
291size_t scm_take_from_input_buffers (SCM port, char *dest, size_t read_len)
292{
92c2555f 293 scm_t_port *pt = SCM_PTAB_ENTRY (port);
c2da2648
GH
294 size_t chars_read = 0;
295 size_t from_buf = min (pt->read_end - pt->read_pos, read_len);
296
297 if (from_buf > 0)
298 {
299 memcpy (dest, pt->read_pos, from_buf);
300 pt->read_pos += from_buf;
301 chars_read += from_buf;
302 read_len -= from_buf;
303 dest += from_buf;
304 }
305
306 /* if putback was active, try the real input buffer too. */
307 if (pt->read_buf == pt->putback_buf)
308 {
309 from_buf = min (pt->saved_read_end - pt->saved_read_pos, read_len);
310 if (from_buf > 0)
311 {
312 memcpy (dest, pt->saved_read_pos, from_buf);
313 pt->saved_read_pos += from_buf;
314 chars_read += from_buf;
315 }
316 }
317 return chars_read;
318}
319
6c951427 320/* Clear a port's read buffers, returning the contents. */
a1ec6916 321SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
1bbd0b84 322 (SCM port),
4a151b3d
GH
323 "This procedure clears a port's input buffers, similar\n"
324 "to the way that force-output clears the output buffer. The\n"
325 "contents of the buffers are returned as a single string, e.g.,\n"
326 "\n"
327 "@lisp\n"
328 "(define p (open-input-file ...))\n"
329 "(drain-input p) => empty string, nothing buffered yet.\n"
330 "(unread-char (read-char p) p)\n"
331 "(drain-input p) => initial chars from p, up to the buffer size.\n"
332 "@end lisp\n\n"
333 "Draining the buffers may be useful for cleanly finishing\n"
334 "buffered I/O so that the file descriptor can be used directly\n"
335 "for further input.")
1bbd0b84 336#define FUNC_NAME s_scm_drain_input
ee149d03 337{
840ae05d 338 SCM result;
3a5fb14d 339 char *data;
28a6e1b0 340 scm_t_port *pt;
c014a02e 341 long count;
ee149d03 342
34d19ef6 343 SCM_VALIDATE_OPINPORT (1, port);
28a6e1b0 344 pt = SCM_PTAB_ENTRY (port);
840ae05d 345
6c951427
GH
346 count = pt->read_end - pt->read_pos;
347 if (pt->read_buf == pt->putback_buf)
348 count += pt->saved_read_end - pt->saved_read_pos;
840ae05d 349
67a72dc1
AW
350 if (count)
351 {
352 result = scm_i_make_string (count, &data);
353 scm_take_from_input_buffers (port, data, count);
354 }
355 else
356 result = scm_nullstr;
357
840ae05d 358 return result;
ee149d03 359}
1bbd0b84 360#undef FUNC_NAME
0f2d19dd
JB
361
362\f
d68fee48 363/* Standard ports --- current input, output, error, and more(!). */
0f2d19dd 364
889975e5
MG
365static SCM cur_inport_fluid = 0;
366static SCM cur_outport_fluid = 0;
367static SCM cur_errport_fluid = 0;
368static SCM cur_loadport_fluid = 0;
9de87eea 369
3b3b36dd 370SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
e1546b65
MG
371 (),
372 "Return the current input port. This is the default port used\n"
373 "by many input procedures. Initially, @code{current-input-port}\n"
374 "returns the @dfn{standard input} in Unix and C terminology.")
1bbd0b84 375#define FUNC_NAME s_scm_current_input_port
0f2d19dd 376{
889975e5
MG
377 if (cur_inport_fluid)
378 return scm_fluid_ref (cur_inport_fluid);
379 else
380 return SCM_BOOL_F;
0f2d19dd 381}
1bbd0b84 382#undef FUNC_NAME
0f2d19dd 383
3b3b36dd 384SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
e1546b65
MG
385 (),
386 "Return the current output port. This is the default port used\n"
9401323e 387 "by many output procedures. Initially,\n"
e1546b65
MG
388 "@code{current-output-port} returns the @dfn{standard output} in\n"
389 "Unix and C terminology.")
1bbd0b84 390#define FUNC_NAME s_scm_current_output_port
0f2d19dd 391{
889975e5
MG
392 if (cur_outport_fluid)
393 return scm_fluid_ref (cur_outport_fluid);
394 else
395 return SCM_BOOL_F;
0f2d19dd 396}
1bbd0b84 397#undef FUNC_NAME
0f2d19dd 398
3b3b36dd 399SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
1bbd0b84 400 (),
b380b885
MD
401 "Return the port to which errors and warnings should be sent (the\n"
402 "@dfn{standard error} in Unix and C terminology).")
1bbd0b84 403#define FUNC_NAME s_scm_current_error_port
0f2d19dd 404{
889975e5
MG
405 if (cur_errport_fluid)
406 return scm_fluid_ref (cur_errport_fluid);
407 else
408 return SCM_BOOL_F;
0f2d19dd 409}
1bbd0b84 410#undef FUNC_NAME
0f2d19dd 411
3b3b36dd 412SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
e1546b65 413 (),
b450f070 414 "Return the current-load-port.\n"
e1546b65 415 "The load port is used internally by @code{primitive-load}.")
1bbd0b84 416#define FUNC_NAME s_scm_current_load_port
31614d8e 417{
9de87eea 418 return scm_fluid_ref (cur_loadport_fluid);
31614d8e 419}
1bbd0b84 420#undef FUNC_NAME
31614d8e 421
3b3b36dd 422SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
1bbd0b84 423 (SCM port),
8f85c0c6
NJ
424 "@deffnx {Scheme Procedure} set-current-output-port port\n"
425 "@deffnx {Scheme Procedure} set-current-error-port port\n"
b380b885
MD
426 "Change the ports returned by @code{current-input-port},\n"
427 "@code{current-output-port} and @code{current-error-port}, respectively,\n"
428 "so that they use the supplied @var{port} for input or output.")
1bbd0b84 429#define FUNC_NAME s_scm_set_current_input_port
0f2d19dd 430{
9de87eea 431 SCM oinp = scm_fluid_ref (cur_inport_fluid);
34d19ef6 432 SCM_VALIDATE_OPINPORT (1, port);
9de87eea 433 scm_fluid_set_x (cur_inport_fluid, port);
0f2d19dd
JB
434 return oinp;
435}
1bbd0b84 436#undef FUNC_NAME
0f2d19dd
JB
437
438
3b3b36dd 439SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
e1546b65
MG
440 (SCM port),
441 "Set the current default output port to @var{port}.")
1bbd0b84 442#define FUNC_NAME s_scm_set_current_output_port
0f2d19dd 443{
9de87eea 444 SCM ooutp = scm_fluid_ref (cur_outport_fluid);
78446828 445 port = SCM_COERCE_OUTPORT (port);
34d19ef6 446 SCM_VALIDATE_OPOUTPORT (1, port);
9de87eea 447 scm_fluid_set_x (cur_outport_fluid, port);
0f2d19dd
JB
448 return ooutp;
449}
1bbd0b84 450#undef FUNC_NAME
0f2d19dd
JB
451
452
3b3b36dd 453SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
e1546b65
MG
454 (SCM port),
455 "Set the current default error port to @var{port}.")
1bbd0b84 456#define FUNC_NAME s_scm_set_current_error_port
0f2d19dd 457{
9de87eea 458 SCM oerrp = scm_fluid_ref (cur_errport_fluid);
78446828 459 port = SCM_COERCE_OUTPORT (port);
34d19ef6 460 SCM_VALIDATE_OPOUTPORT (1, port);
9de87eea 461 scm_fluid_set_x (cur_errport_fluid, port);
0f2d19dd
JB
462 return oerrp;
463}
1bbd0b84 464#undef FUNC_NAME
0f2d19dd 465
185e369a 466void
661ae7ab 467scm_dynwind_current_input_port (SCM port)
9de87eea 468#define FUNC_NAME NULL
185e369a 469{
9de87eea 470 SCM_VALIDATE_OPINPORT (1, port);
661ae7ab 471 scm_dynwind_fluid (cur_inport_fluid, port);
185e369a 472}
9de87eea 473#undef FUNC_NAME
185e369a
MV
474
475void
661ae7ab 476scm_dynwind_current_output_port (SCM port)
9de87eea 477#define FUNC_NAME NULL
185e369a 478{
9de87eea
MV
479 port = SCM_COERCE_OUTPORT (port);
480 SCM_VALIDATE_OPOUTPORT (1, port);
661ae7ab 481 scm_dynwind_fluid (cur_outport_fluid, port);
185e369a 482}
9de87eea 483#undef FUNC_NAME
185e369a
MV
484
485void
661ae7ab 486scm_dynwind_current_error_port (SCM port)
9de87eea
MV
487#define FUNC_NAME NULL
488{
489 port = SCM_COERCE_OUTPORT (port);
490 SCM_VALIDATE_OPOUTPORT (1, port);
661ae7ab 491 scm_dynwind_fluid (cur_errport_fluid, port);
9de87eea
MV
492}
493#undef FUNC_NAME
494
495void
661ae7ab 496scm_i_dynwind_current_load_port (SCM port)
185e369a 497{
661ae7ab 498 scm_dynwind_fluid (cur_loadport_fluid, port);
185e369a
MV
499}
500
0f2d19dd 501\f
840ae05d 502/* The port table --- an array of pointers to ports. */
0f2d19dd 503
5dbc6c06
HWN
504/*
505 We need a global registry of ports to flush them all at exit, and to
506 get all the ports matching a file descriptor.
507 */
508SCM scm_i_port_weak_hash;
0f2d19dd 509
9de87eea 510scm_i_pthread_mutex_t scm_i_port_table_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
b9ad392e 511
651a0735
LC
512\f
513/* Port finalization. */
514
1cc91f1b 515
651a0735
LC
516static void finalize_port (GC_PTR, GC_PTR);
517
518/* Register a finalizer for PORT, if needed by its port type. */
519static SCM_C_INLINE_KEYWORD void
520register_finalizer_for_port (SCM port)
521{
522 long port_type;
523
524 port_type = SCM_TC2PTOBNUM (SCM_CELL_TYPE (port));
525 if (scm_ptobs[port_type].free)
526 {
527 GC_finalization_proc prev_finalizer;
528 GC_PTR prev_finalization_data;
529
530 GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (port), finalize_port, 0,
531 &prev_finalizer,
532 &prev_finalization_data);
533 }
534}
535
536/* Finalize the object (a port) pointed to by PTR. */
537static void
538finalize_port (GC_PTR ptr, GC_PTR data)
539{
540 long port_type;
541 SCM port = PTR2SCM (ptr);
542
543 if (!SCM_PORTP (port))
544 abort ();
545
546 if (SCM_OPENP (port))
547 {
548 if (SCM_REVEALED (port) > 0)
549 /* Keep "revealed" ports alive and re-register a finalizer. */
550 register_finalizer_for_port (port);
551 else
552 {
553 port_type = SCM_TC2PTOBNUM (SCM_CELL_TYPE (port));
554 if (port_type >= scm_numptob)
555 abort ();
556
557 if (scm_ptobs[port_type].free)
558 /* Yes, I really do mean `.free' rather than `.close'. `.close'
559 is for explicit `close-port' by user. */
560 scm_ptobs[port_type].free (port);
561
562 SCM_SETSTREAM (port, 0);
563 SCM_CLR_PORT_OPEN_FLAG (port);
651a0735
LC
564
565 scm_gc_ports_collected++;
566 }
567 }
568}
569
570
571
572\f
573
574/* This function is not and should not be thread safe. */
da220f27
HWN
575SCM
576scm_new_port_table_entry (scm_t_bits tag)
402788a9 577#define FUNC_NAME "scm_new_port_table_entry"
0f2d19dd 578{
85835e59
HWN
579 /*
580 We initialize the cell to empty, this is in case scm_gc_calloc
581 triggers GC ; we don't want the GC to scan a half-finished Z.
582 */
583
67329a9e 584 SCM z = scm_cons (SCM_EOL, SCM_EOL);
39e8f371 585 scm_t_port *entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
889975e5 586 const char *enc;
5f16b897 587
840ae05d 588 entry->file_name = SCM_BOOL_F;
61e452ba 589 entry->rw_active = SCM_PORT_NEITHER;
5dbc6c06 590 entry->port = z;
889975e5
MG
591 /* Initialize this port with the thread's current default
592 encoding. */
593 if ((enc = scm_i_get_port_encoding (SCM_BOOL_F)) == NULL)
594 entry->encoding = NULL;
595 else
682d78d0 596 entry->encoding = scm_gc_strdup (enc, "port");
889975e5 597 entry->ilseq_handler = scm_i_get_conversion_strategy (SCM_BOOL_F);
5f16b897 598
5dbc6c06
HWN
599 SCM_SET_CELL_TYPE (z, tag);
600 SCM_SETPTAB_ENTRY (z, entry);
840ae05d 601
5dbc6c06 602 scm_hashq_set_x (scm_i_port_weak_hash, z, SCM_BOOL_F);
651a0735
LC
603
604 /* For each new port, register a finalizer so that it port type's free
605 function can be invoked eventually. */
606 register_finalizer_for_port (z);
607
da220f27 608 return z;
0f2d19dd 609}
c6c79933 610#undef FUNC_NAME
0f2d19dd 611
67329a9e
HWN
612#if SCM_ENABLE_DEPRECATED==1
613SCM_API scm_t_port *
614scm_add_to_port_table (SCM port)
615{
616 SCM z = scm_new_port_table_entry (scm_tc7_port);
617 scm_t_port * pt = SCM_PTAB_ENTRY(z);
618
619 pt->port = port;
5dbc6c06
HWN
620 SCM_SETCAR (z, SCM_EOL);
621 SCM_SETCDR (z, SCM_EOL);
85835e59 622 SCM_SETPTAB_ENTRY (port, pt);
67329a9e
HWN
623 return pt;
624}
625#endif
626
627
6c951427 628/* Remove a port from the table and destroy it. */
b9ad392e
MD
629
630/* This function is not and should not be thread safe. */
0f2d19dd 631void
5dbc6c06
HWN
632scm_i_remove_port (SCM port)
633#define FUNC_NAME "scm_remove_port"
0f2d19dd 634{
92c2555f 635 scm_t_port *p = SCM_PTAB_ENTRY (port);
682d78d0
LC
636
637 scm_port_non_buffer (p);
638
639 p->putback_buf = NULL;
640 p->putback_buf_size = 0;
5dbc6c06 641
0f2d19dd 642 SCM_SETPTAB_ENTRY (port, 0);
5dbc6c06 643 scm_hashq_remove_x (scm_i_port_weak_hash, port);
0f2d19dd 644}
db4b4ca6
DH
645#undef FUNC_NAME
646
0f2d19dd 647
b450f070 648/* Functions for debugging. */
5dbc6c06 649#ifdef GUILE_DEBUG
3b3b36dd 650SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
b450f070 651 (),
1e6808ea 652 "Return the number of ports in the port table. @code{pt-size}\n"
5352393c 653 "is only included in @code{--enable-guile-debug} builds.")
1bbd0b84 654#define FUNC_NAME s_scm_pt_size
0f2d19dd 655{
5dbc6c06 656 return scm_from_int (SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash));
0f2d19dd 657}
1bbd0b84 658#undef FUNC_NAME
0f2d19dd
JB
659#endif
660
70df8af6 661void
92c2555f 662scm_port_non_buffer (scm_t_port *pt)
70df8af6
GH
663{
664 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
665 pt->write_buf = pt->write_pos = &pt->shortbuf;
666 pt->read_buf_size = pt->write_buf_size = 1;
667 pt->write_end = pt->write_buf + pt->write_buf_size;
668}
0f2d19dd 669
d68fee48
JB
670\f
671/* Revealed counts --- an oddity inherited from SCSH. */
672
8b13c6b3
GH
673/* Find a port in the table and return its revealed count.
674 Also used by the garbage collector.
0f2d19dd 675 */
1cc91f1b 676
0f2d19dd 677int
a284e297 678scm_revealed_count (SCM port)
0f2d19dd
JB
679{
680 return SCM_REVEALED(port);
681}
682
683
684
685/* Return the revealed count for a port. */
686
3b3b36dd 687SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
1bbd0b84 688 (SCM port),
1e6808ea 689 "Return the revealed count for @var{port}.")
1bbd0b84 690#define FUNC_NAME s_scm_port_revealed
0f2d19dd 691{
78446828 692 port = SCM_COERCE_OUTPORT (port);
34d19ef6 693 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 694 return scm_from_int (scm_revealed_count (port));
0f2d19dd 695}
1bbd0b84 696#undef FUNC_NAME
0f2d19dd
JB
697
698/* Set the revealed count for a port. */
3b3b36dd 699SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
1bbd0b84 700 (SCM port, SCM rcount),
b450f070 701 "Sets the revealed count for a port to a given value.\n"
b380b885 702 "The return value is unspecified.")
1bbd0b84 703#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 704{
78446828 705 port = SCM_COERCE_OUTPORT (port);
34d19ef6 706 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 707 SCM_REVEALED (port) = scm_to_int (rcount);
8b13c6b3 708 return SCM_UNSPECIFIED;
0f2d19dd 709}
1bbd0b84 710#undef FUNC_NAME
0f2d19dd 711
d68fee48
JB
712
713\f
714/* Retrieving a port's mode. */
715
eadd48de
GH
716/* Return the flags that characterize a port based on the mode
717 * string used to open a file for that port.
718 *
719 * See PORT FLAGS in scm.h
720 */
721
3a5fb14d 722static long
889975e5 723scm_i_mode_bits_n (SCM modes)
3a5fb14d
MV
724{
725 return (SCM_OPN
889975e5
MG
726 | (scm_i_string_contains_char (modes, 'r')
727 || scm_i_string_contains_char (modes, '+') ? SCM_RDNG : 0)
728 | (scm_i_string_contains_char (modes, 'w')
729 || scm_i_string_contains_char (modes, 'a')
730 || scm_i_string_contains_char (modes, '+') ? SCM_WRTNG : 0)
731 | (scm_i_string_contains_char (modes, '0') ? SCM_BUF0 : 0)
732 | (scm_i_string_contains_char (modes, 'l') ? SCM_BUFLINE : 0));
3a5fb14d
MV
733}
734
eadd48de 735long
a284e297 736scm_mode_bits (char *modes)
eadd48de 737{
889975e5 738 return scm_i_mode_bits (scm_from_locale_string (modes));
eadd48de
GH
739}
740
d617ee18
MV
741long
742scm_i_mode_bits (SCM modes)
743{
744 long bits;
745
746 if (!scm_is_string (modes))
747 scm_wrong_type_arg_msg (NULL, 0, modes, "string");
748
889975e5 749 bits = scm_i_mode_bits_n (modes);
d617ee18
MV
750 scm_remember_upto_here_1 (modes);
751 return bits;
752}
eadd48de
GH
753
754/* Return the mode flags from an open port.
755 * Some modes such as "append" are only used when opening
756 * a file and are not returned here. */
757
3b3b36dd 758SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
1bbd0b84 759 (SCM port),
1e6808ea
MG
760 "Return the port modes associated with the open port @var{port}.\n"
761 "These will not necessarily be identical to the modes used when\n"
762 "the port was opened, since modes such as \"append\" which are\n"
763 "used only during port creation are not retained.")
1bbd0b84 764#define FUNC_NAME s_scm_port_mode
eadd48de 765{
26a3038d 766 char modes[4];
eadd48de 767 modes[0] = '\0';
78446828
MV
768
769 port = SCM_COERCE_OUTPORT (port);
34d19ef6 770 SCM_VALIDATE_OPPORT (1, port);
f9a64404
DH
771 if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
772 if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de
GH
773 strcpy (modes, "r+");
774 else
775 strcpy (modes, "r");
776 }
f9a64404 777 else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de 778 strcpy (modes, "w");
f9a64404 779 if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
eadd48de 780 strcat (modes, "0");
3a5fb14d 781 return scm_from_locale_string (modes);
eadd48de 782}
1bbd0b84 783#undef FUNC_NAME
eadd48de
GH
784
785
d68fee48
JB
786\f
787/* Closing ports. */
788
0f2d19dd
JB
789/* scm_close_port
790 * Call the close operation on a port object.
eadd48de 791 * see also scm_close.
0f2d19dd 792 */
3b3b36dd 793SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
1bbd0b84 794 (SCM port),
1e6808ea
MG
795 "Close the specified port object. Return @code{#t} if it\n"
796 "successfully closes a port or @code{#f} if it was already\n"
797 "closed. An exception may be raised if an error occurs, for\n"
798 "example when flushing buffered output. See also @ref{Ports and\n"
799 "File Descriptors, close}, for a procedure which can close file\n"
800 "descriptors.")
1bbd0b84 801#define FUNC_NAME s_scm_close_port
0f2d19dd 802{
1be6b49c 803 size_t i;
eadd48de
GH
804 int rv;
805
78446828
MV
806 port = SCM_COERCE_OUTPORT (port);
807
7a754ca6 808 SCM_VALIDATE_PORT (1, port);
0f2d19dd 809 if (SCM_CLOSEDP (port))
eadd48de 810 return SCM_BOOL_F;
0f2d19dd 811 i = SCM_PTOBNUM (port);
affc96b5
GH
812 if (scm_ptobs[i].close)
813 rv = (scm_ptobs[i].close) (port);
eadd48de
GH
814 else
815 rv = 0;
9de87eea 816 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
5dbc6c06 817 scm_i_remove_port (port);
9de87eea 818 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
22a52da1 819 SCM_CLR_PORT_OPEN_FLAG (port);
7888309b 820 return scm_from_bool (rv >= 0);
7a754ca6
MD
821}
822#undef FUNC_NAME
823
824SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
825 (SCM port),
826 "Close the specified input port object. The routine has no effect if\n"
827 "the file has already been closed. An exception may be raised if an\n"
828 "error occurs. The value returned is unspecified.\n\n"
829 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
830 "which can close file descriptors.")
831#define FUNC_NAME s_scm_close_input_port
832{
833 SCM_VALIDATE_INPUT_PORT (1, port);
834 scm_close_port (port);
835 return SCM_UNSPECIFIED;
836}
837#undef FUNC_NAME
838
839SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
840 (SCM port),
841 "Close the specified output port object. The routine has no effect if\n"
842 "the file has already been closed. An exception may be raised if an\n"
843 "error occurs. The value returned is unspecified.\n\n"
844 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
845 "which can close file descriptors.")
846#define FUNC_NAME s_scm_close_output_port
847{
848 port = SCM_COERCE_OUTPORT (port);
849 SCM_VALIDATE_OUTPUT_PORT (1, port);
850 scm_close_port (port);
851 return SCM_UNSPECIFIED;
0f2d19dd 852}
1bbd0b84 853#undef FUNC_NAME
0f2d19dd 854
5dbc6c06
HWN
855static SCM
856scm_i_collect_keys_in_vector (void *closure, SCM key, SCM value, SCM result)
857{
858 int *i = (int*) closure;
859 scm_c_vector_set_x (result, *i, key);
860 (*i)++;
861
862 return result;
863}
864
c536b4b3
MV
865void
866scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
c2ca4493 867{
5dbc6c06 868 int i = 0;
3a5fb14d 869 size_t n;
fdfe6305
MV
870 SCM ports;
871
fdfe6305
MV
872 /* Even without pre-emptive multithreading, running arbitrary code
873 while scanning the port table is unsafe because the port table
3a5fb14d
MV
874 can change arbitrarily (from a GC, for example). So we first
875 collect the ports into a vector. -mvo */
fdfe6305 876
9de87eea 877 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
5dbc6c06 878 n = SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash);
9de87eea 879 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
4057a3e0 880 ports = scm_c_make_vector (n, SCM_BOOL_F);
3a5fb14d 881
5dbc6c06
HWN
882 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
883 ports = scm_internal_hash_fold (scm_i_collect_keys_in_vector, &i,
884 ports, scm_i_port_weak_hash);
9de87eea 885 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
3a5fb14d 886
5dbc6c06
HWN
887 for (i = 0; i < n; i++) {
888 SCM p = SCM_SIMPLE_VECTOR_REF (ports, i);
889 if (SCM_PORTP (p))
890 proc (data, p);
891 }
bd83658e
RB
892
893 scm_remember_upto_here_1 (ports);
c536b4b3 894}
fdfe6305 895
c536b4b3
MV
896SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
897 (SCM proc),
898 "Apply @var{proc} to each port in the Guile port table\n"
899 "in turn. The return value is unspecified. More specifically,\n"
900 "@var{proc} is applied exactly once to every port that exists\n"
901 "in the system at the time @var{port-for-each} is invoked.\n"
902 "Changes to the port table while @var{port-for-each} is running\n"
903 "have no effect as far as @var{port-for-each} is concerned.")
904#define FUNC_NAME s_scm_port_for_each
905{
906 SCM_VALIDATE_PROC (1, proc);
907
908 scm_c_port_for_each ((void (*)(void*,SCM))scm_call_1, proc);
c2ca4493
GH
909 return SCM_UNSPECIFIED;
910}
911#undef FUNC_NAME
912
c536b4b3 913
d68fee48
JB
914\f
915/* Utter miscellany. Gosh, we should clean this up some time. */
916
3b3b36dd 917SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
1bbd0b84 918 (SCM x),
1e6808ea
MG
919 "Return @code{#t} if @var{x} is an input port, otherwise return\n"
920 "@code{#f}. Any object satisfying this predicate also satisfies\n"
921 "@code{port?}.")
1bbd0b84 922#define FUNC_NAME s_scm_input_port_p
0f2d19dd 923{
7888309b 924 return scm_from_bool (SCM_INPUT_PORT_P (x));
0f2d19dd 925}
1bbd0b84 926#undef FUNC_NAME
0f2d19dd 927
3b3b36dd 928SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
1bbd0b84 929 (SCM x),
1e6808ea
MG
930 "Return @code{#t} if @var{x} is an output port, otherwise return\n"
931 "@code{#f}. Any object satisfying this predicate also satisfies\n"
932 "@code{port?}.")
1bbd0b84 933#define FUNC_NAME s_scm_output_port_p
0f2d19dd 934{
82893676 935 x = SCM_COERCE_OUTPORT (x);
7888309b 936 return scm_from_bool (SCM_OUTPUT_PORT_P (x));
0f2d19dd 937}
1bbd0b84 938#undef FUNC_NAME
0f2d19dd 939
eb5c0a2a
GH
940SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
941 (SCM x),
1e6808ea 942 "Return a boolean indicating whether @var{x} is a port.\n"
5352393c
MG
943 "Equivalent to @code{(or (input-port? @var{x}) (output-port?\n"
944 "@var{x}))}.")
eb5c0a2a
GH
945#define FUNC_NAME s_scm_port_p
946{
7888309b 947 return scm_from_bool (SCM_PORTP (x));
eb5c0a2a
GH
948}
949#undef FUNC_NAME
950
3b3b36dd 951SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
1bbd0b84 952 (SCM port),
1e6808ea
MG
953 "Return @code{#t} if @var{port} is closed or @code{#f} if it is\n"
954 "open.")
1bbd0b84 955#define FUNC_NAME s_scm_port_closed_p
60d0643d 956{
34d19ef6 957 SCM_VALIDATE_PORT (1, port);
7888309b 958 return scm_from_bool (!SCM_OPPORTP (port));
60d0643d 959}
1bbd0b84 960#undef FUNC_NAME
0f2d19dd 961
3b3b36dd 962SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
1bbd0b84 963 (SCM x),
1e6808ea
MG
964 "Return @code{#t} if @var{x} is an end-of-file object; otherwise\n"
965 "return @code{#f}.")
1bbd0b84 966#define FUNC_NAME s_scm_eof_object_p
0f2d19dd 967{
7888309b 968 return scm_from_bool(SCM_EOF_OBJECT_P (x));
0f2d19dd 969}
1bbd0b84 970#undef FUNC_NAME
0f2d19dd 971
3b3b36dd 972SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
1bbd0b84 973 (SCM port),
b380b885 974 "Flush the specified output port, or the current output port if @var{port}\n"
9401323e 975 "is omitted. The current output buffer contents are passed to the\n"
b380b885
MD
976 "underlying port implementation (e.g., in the case of fports, the\n"
977 "data will be written to the file and the output buffer will be cleared.)\n"
978 "It has no effect on an unbuffered port.\n\n"
979 "The return value is unspecified.")
1bbd0b84 980#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
981{
982 if (SCM_UNBNDP (port))
9de87eea 983 port = scm_current_output_port ();
0f2d19dd 984 else
78446828
MV
985 {
986 port = SCM_COERCE_OUTPORT (port);
34d19ef6 987 SCM_VALIDATE_OPOUTPORT (1, port);
78446828 988 }
affc96b5 989 scm_flush (port);
ee149d03 990 return SCM_UNSPECIFIED;
0f2d19dd 991}
1bbd0b84 992#undef FUNC_NAME
0f2d19dd 993
5dbc6c06
HWN
994
995static void
61d3568b 996flush_output_port (void *closure, SCM port)
5dbc6c06 997{
5dbc6c06
HWN
998 if (SCM_OPOUTPORTP (port))
999 scm_flush (port);
1000}
1001
a1ec6916 1002SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
1bbd0b84 1003 (),
b380b885
MD
1004 "Equivalent to calling @code{force-output} on\n"
1005 "all open output ports. The return value is unspecified.")
1bbd0b84 1006#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c 1007{
5dbc6c06 1008 scm_c_port_for_each (&flush_output_port, NULL);
89ea5b7c
GH
1009 return SCM_UNSPECIFIED;
1010}
1bbd0b84 1011#undef FUNC_NAME
0f2d19dd 1012
3b3b36dd 1013SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1bbd0b84 1014 (SCM port),
1e6808ea
MG
1015 "Return the next character available from @var{port}, updating\n"
1016 "@var{port} to point to the following character. If no more\n"
1017 "characters are available, the end-of-file object is returned.")
1bbd0b84 1018#define FUNC_NAME s_scm_read_char
0f2d19dd 1019{
889975e5 1020 scm_t_wchar c;
0f2d19dd 1021 if (SCM_UNBNDP (port))
9de87eea 1022 port = scm_current_input_port ();
34d19ef6 1023 SCM_VALIDATE_OPINPORT (1, port);
b7f3516f 1024 c = scm_getc (port);
0f2d19dd
JB
1025 if (EOF == c)
1026 return SCM_EOF_VAL;
7866a09b 1027 return SCM_MAKE_CHAR (c);
0f2d19dd 1028}
1bbd0b84 1029#undef FUNC_NAME
0f2d19dd 1030
889975e5
MG
1031#define SCM_MBCHAR_BUF_SIZE (4)
1032
fd5eec2b
LC
1033/* Read a codepoint from PORT and return it. Fill BUF with the byte
1034 representation of the codepoint in PORT's encoding, and set *LEN to
1035 the length in bytes of that representation. Raise an error on
1036 failure. */
1037static scm_t_wchar
1038get_codepoint (SCM port, char buf[SCM_MBCHAR_BUF_SIZE], size_t *len)
889975e5
MG
1039{
1040 int c;
fd5eec2b 1041 size_t bufcount = 0;
63479112 1042 scm_t_uint32 result_buf;
889975e5
MG
1043 scm_t_wchar codepoint = 0;
1044 scm_t_uint32 *u32;
1045 size_t u32len;
1046 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1047
1048 c = scm_get_byte_or_eof (port);
1049 if (c == EOF)
1050 return (scm_t_wchar) EOF;
1051
1052 buf[0] = c;
1053 bufcount++;
1054
1055 if (pt->encoding == NULL)
63479112 1056 {
889975e5 1057 /* The encoding is Latin-1: bytes are characters. */
8736ef70 1058 codepoint = (unsigned char) buf[0];
889975e5
MG
1059 goto success;
1060 }
1061
1062 for (;;)
1063 {
63479112
LC
1064 u32len = sizeof (result_buf) / sizeof (scm_t_uint32);
1065 u32 = u32_conv_from_encoding (pt->encoding,
1066 (enum iconv_ilseq_handler) pt->ilseq_handler,
1067 buf, bufcount, NULL, &result_buf, &u32len);
889975e5
MG
1068 if (u32 == NULL || u32len == 0)
1069 {
1070 if (errno == ENOMEM)
1071 scm_memory_error ("Input decoding");
63479112 1072
889975e5
MG
1073 /* Otherwise errno is EILSEQ or EINVAL, so perhaps more
1074 bytes are needed. Keep looping. */
1075 }
63479112 1076 else
889975e5
MG
1077 {
1078 /* Complete codepoint found. */
1079 codepoint = u32[0];
63479112
LC
1080
1081 if (SCM_UNLIKELY (u32 != &result_buf))
1082 /* libunistring up to 0.9.3 (included) would always heap-allocate
1083 the result even when a large-enough RESULT_BUF is supplied, see
1084 <http://lists.gnu.org/archive/html/bug-libunistring/2010-07/msg00003.html>. */
1085 free (u32);
1086
889975e5
MG
1087 goto success;
1088 }
1089
1090 if (bufcount == SCM_MBCHAR_BUF_SIZE)
1091 {
1092 /* We've read several bytes and didn't find a good
1093 codepoint. Give up. */
1094 goto failure;
1095 }
1096
1097 c = scm_get_byte_or_eof (port);
1098
1099 if (c == EOF)
1100 {
1101 /* EOF before a complete character was read. Push it all
1102 back and return EOF. */
1103 while (bufcount > 0)
1104 {
1105 /* FIXME: this will probably cause errors in the port column. */
1106 scm_unget_byte (buf[bufcount-1], port);
1107 bufcount --;
1108 }
1109 return EOF;
1110 }
1111
1112 if (c == '\n')
1113 {
1114 /* It is always invalid to have EOL in the middle of a
1115 multibyte character. */
1116 scm_unget_byte ('\n', port);
1117 goto failure;
1118 }
1119
1120 buf[bufcount++] = c;
1121 }
1122
1123 success:
1124 switch (codepoint)
1125 {
1126 case '\a':
1127 break;
1128 case '\b':
1129 SCM_DECCOL (port);
1130 break;
1131 case '\n':
1132 SCM_INCLINE (port);
1133 break;
1134 case '\r':
1135 SCM_ZEROCOL (port);
1136 break;
1137 case '\t':
1138 SCM_TABCOL (port);
1139 break;
1140 default:
1141 SCM_INCCOL (port);
1142 break;
1143 }
1144
fd5eec2b
LC
1145 *len = bufcount;
1146
889975e5
MG
1147 return codepoint;
1148
1149 failure:
1150 {
1151 char *err_buf;
1152 SCM err_str = scm_i_make_string (bufcount, &err_buf);
1153 memcpy (err_buf, buf, bufcount);
1154
1155 if (errno == EILSEQ)
1156 scm_misc_error (NULL, "input encoding error for ~s: ~s",
1157 scm_list_2 (scm_from_locale_string (scm_i_get_port_encoding (port)),
1158 err_str));
1159 else
1160 scm_misc_error (NULL, "input encoding error (invalid) for ~s: ~s\n",
1161 scm_list_2 (scm_from_locale_string (scm_i_get_port_encoding (port)),
1162 err_str));
1163 }
1164
1165 /* Never gets here. */
1166 return 0;
1167}
1168
fd5eec2b
LC
1169/* Read a codepoint from PORT and return it. */
1170scm_t_wchar
1171scm_getc (SCM port)
1172{
1173 size_t len;
1174 char buf[SCM_MBCHAR_BUF_SIZE];
1175
1176 return get_codepoint (port, buf, &len);
1177}
889975e5 1178
5c070ca7 1179/* this should only be called when the read buffer is empty. it
affc96b5 1180 tries to refill the read buffer. it returns the first char from
5c070ca7 1181 the port, which is either EOF or *(pt->read_pos). */
6c951427 1182int
affc96b5 1183scm_fill_input (SCM port)
6c951427 1184{
92c2555f 1185 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e 1186
b5cb4464
NJ
1187 assert (pt->read_pos == pt->read_end);
1188
6c951427
GH
1189 if (pt->read_buf == pt->putback_buf)
1190 {
1191 /* finished reading put-back chars. */
1192 pt->read_buf = pt->saved_read_buf;
1193 pt->read_pos = pt->saved_read_pos;
1194 pt->read_end = pt->saved_read_end;
1195 pt->read_buf_size = pt->saved_read_buf_size;
1196 if (pt->read_pos < pt->read_end)
5c070ca7 1197 return *(pt->read_pos);
6c951427 1198 }
affc96b5 1199 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
1200}
1201
3cb988bd 1202
6fe692e9
MD
1203/* scm_lfwrite
1204 *
53802ea8
MV
1205 * This function differs from scm_c_write; it updates port line and
1206 * column. */
6fe692e9 1207
9c44cd45
MG
1208static void
1209update_port_lf (scm_t_wchar c, SCM port)
1210{
1211 if (c == '\a')
b0799290 1212 ; /* Do nothing. */
9c44cd45 1213 else if (c == '\b')
b0799290 1214 SCM_DECCOL (port);
9c44cd45 1215 else if (c == '\n')
b0799290 1216 SCM_INCLINE (port);
9c44cd45 1217 else if (c == '\r')
b0799290 1218 SCM_ZEROCOL (port);
9c44cd45 1219 else if (c == '\t')
b0799290 1220 SCM_TABCOL (port);
9c44cd45 1221 else
b0799290 1222 SCM_INCCOL (port);
9c44cd45
MG
1223}
1224
1225void
1be6b49c 1226scm_lfwrite (const char *ptr, size_t size, SCM port)
ee149d03 1227{
92c2555f
MV
1228 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1229 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 1230
840ae05d 1231 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1232 scm_end_input (port);
283a1a0e 1233
31703ab8 1234 ptob->write (port, ptr, size);
840ae05d 1235
9c44cd45
MG
1236 for (; size; ptr++, size--)
1237 update_port_lf ((scm_t_wchar) (unsigned char) *ptr, port);
1238
1239 if (pt->rw_random)
1240 pt->rw_active = SCM_PORT_WRITE;
1241}
1242
1243/* Write a scheme string STR to PORT from START inclusive to END
1244 exclusive. */
1245void
1246scm_lfwrite_substr (SCM str, size_t start, size_t end, SCM port)
1247{
1248 size_t i, size = scm_i_string_length (str);
1249 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1250 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
1251 scm_t_wchar p;
1252 char *buf;
1253 size_t len;
1254
1255 if (pt->rw_active == SCM_PORT_READ)
1256 scm_end_input (port);
1257
bd4911ef 1258 if (end == (size_t) (-1))
9c44cd45
MG
1259 end = size;
1260 size = end - start;
1261
06b96190
MG
1262 /* Note that making a substring will likely take the
1263 stringbuf_write_mutex. So, one shouldn't use scm_lfwrite_substr
1264 if the stringbuf write mutex may still be held elsewhere. */
9c44cd45 1265 buf = scm_to_stringn (scm_c_substring (str, start, end), &len,
889975e5 1266 pt->encoding, pt->ilseq_handler);
9c44cd45
MG
1267 ptob->write (port, buf, len);
1268 free (buf);
1269
1270 for (i = 0; i < size; i++)
1271 {
1272 p = scm_i_string_ref (str, i + start);
1273 update_port_lf (p, port);
53802ea8 1274 }
53802ea8 1275
840ae05d
JB
1276 if (pt->rw_random)
1277 pt->rw_active = SCM_PORT_WRITE;
ee149d03 1278}
3cb988bd 1279
9c44cd45
MG
1280/* Write a scheme string STR to PORT. */
1281void
1282scm_lfwrite_str (SCM str, SCM port)
1283{
06b96190
MG
1284 size_t i, size = scm_i_string_length (str);
1285 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1286 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
1287 scm_t_wchar p;
1288 char *buf;
1289 size_t len;
1290
1291 if (pt->rw_active == SCM_PORT_READ)
1292 scm_end_input (port);
1293
1294 buf = scm_to_stringn (str, &len,
889975e5 1295 pt->encoding, pt->ilseq_handler);
06b96190
MG
1296 ptob->write (port, buf, len);
1297 free (buf);
1298
1299 for (i = 0; i < size; i++)
1300 {
1301 p = scm_i_string_ref (str, i);
1302 update_port_lf (p, port);
1303 }
1304
1305 if (pt->rw_random)
1306 pt->rw_active = SCM_PORT_WRITE;
9c44cd45
MG
1307}
1308
6fe692e9
MD
1309/* scm_c_read
1310 *
1311 * Used by an application to read arbitrary number of bytes from an
1312 * SCM port. Same semantics as libc read, except that scm_c_read only
1313 * returns less than SIZE bytes if at end-of-file.
1314 *
1315 * Warning: Doesn't update port line and column counts! */
1316
b5cb4464
NJ
1317/* This structure, and the following swap_buffer function, are used
1318 for temporarily swapping a port's own read buffer, and the buffer
1319 that the caller of scm_c_read provides. */
1320struct port_and_swap_buffer
1321{
1322 scm_t_port *pt;
1323 unsigned char *buffer;
1324 size_t size;
1325};
1326
1327static void
1328swap_buffer (void *data)
1329{
1330 struct port_and_swap_buffer *psb = (struct port_and_swap_buffer *) data;
1331 unsigned char *old_buf = psb->pt->read_buf;
1332 size_t old_size = psb->pt->read_buf_size;
1333
1334 /* Make the port use (buffer, size) from the struct. */
1335 psb->pt->read_pos = psb->pt->read_buf = psb->pt->read_end = psb->buffer;
1336 psb->pt->read_buf_size = psb->size;
1337
1338 /* Save the port's old (buffer, size) in the struct. */
1339 psb->buffer = old_buf;
1340 psb->size = old_size;
1341}
1342
1be6b49c
ML
1343size_t
1344scm_c_read (SCM port, void *buffer, size_t size)
693758d5 1345#define FUNC_NAME "scm_c_read"
6fe692e9 1346{
693758d5 1347 scm_t_port *pt;
1be6b49c 1348 size_t n_read = 0, n_available;
b5cb4464 1349 struct port_and_swap_buffer psb;
6fe692e9 1350
693758d5
LC
1351 SCM_VALIDATE_OPINPORT (1, port);
1352
1353 pt = SCM_PTAB_ENTRY (port);
6fe692e9
MD
1354 if (pt->rw_active == SCM_PORT_WRITE)
1355 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
1356
1357 if (pt->rw_random)
1358 pt->rw_active = SCM_PORT_READ;
1359
b5cb4464
NJ
1360 /* Take bytes first from the port's read buffer. */
1361 if (pt->read_pos < pt->read_end)
6fe692e9 1362 {
b5cb4464 1363 n_available = min (size, pt->read_end - pt->read_pos);
6fe692e9 1364 memcpy (buffer, pt->read_pos, n_available);
910d1e40 1365 buffer = (char *) buffer + n_available;
6fe692e9
MD
1366 pt->read_pos += n_available;
1367 n_read += n_available;
6fe692e9 1368 size -= n_available;
6fe692e9
MD
1369 }
1370
b5cb4464
NJ
1371 /* Avoid the scm_dynwind_* costs if we now have enough data. */
1372 if (size == 0)
1373 return n_read;
1374
1375 /* Now we will call scm_fill_input repeatedly until we have read the
1376 requested number of bytes. (Note that a single scm_fill_input
1377 call does not guarantee to fill the whole of the port's read
6d227556 1378 buffer.) */
75192345 1379 if (pt->read_buf_size <= 1 && pt->encoding == NULL)
b5cb4464 1380 {
6d227556
NJ
1381 /* The port that we are reading from is unbuffered - i.e. does
1382 not have its own persistent buffer - but we have a buffer,
1383 provided by our caller, that is the right size for the data
1384 that is wanted. For the following scm_fill_input calls,
1385 therefore, we use the buffer in hand as the port's read
1386 buffer.
1387
1388 We need to make sure that the port's normal (1 byte) buffer
1389 is reinstated in case one of the scm_fill_input () calls
1390 throws an exception; we use the scm_dynwind_* API to achieve
75192345
MG
1391 that.
1392
1393 A consequence of this optimization is that the fill_input
1394 functions can't unget characters. That'll push data to the
1395 pushback buffer instead of this psb buffer. */
1396#if SCM_DEBUG == 1
1397 unsigned char *pback = pt->putback_buf;
1398#endif
6d227556
NJ
1399 psb.pt = pt;
1400 psb.buffer = buffer;
1401 psb.size = size;
1402 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1403 scm_dynwind_rewind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1404 scm_dynwind_unwind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1405
1406 /* Call scm_fill_input until we have all the bytes that we need,
1407 or we hit EOF. */
1408 while (pt->read_buf_size && (scm_fill_input (port) != EOF))
1409 {
1410 pt->read_buf_size -= (pt->read_end - pt->read_pos);
1411 pt->read_pos = pt->read_buf = pt->read_end;
1412 }
75192345
MG
1413#if SCM_DEBUG == 1
1414 if (pback != pt->putback_buf
1415 || pt->read_buf - (unsigned char *) buffer < 0)
1416 scm_misc_error (FUNC_NAME,
1417 "scm_c_read must not call a fill function that pushes "
1418 "back characters onto an unbuffered port", SCM_EOL);
1419#endif
6d227556 1420 n_read += pt->read_buf - (unsigned char *) buffer;
75192345 1421
6d227556
NJ
1422 /* Reinstate the port's normal buffer. */
1423 scm_dynwind_end ();
1424 }
1425 else
1426 {
1427 /* The port has its own buffer. It is important that we use it,
1428 even if it happens to be smaller than our caller's buffer, so
1429 that a custom port implementation's entry points (in
1430 particular, fill_input) can rely on the buffer always being
1431 the same as they first set up. */
1432 while (size && (scm_fill_input (port) != EOF))
1433 {
1434 n_available = min (size, pt->read_end - pt->read_pos);
1435 memcpy (buffer, pt->read_pos, n_available);
1436 buffer = (char *) buffer + n_available;
1437 pt->read_pos += n_available;
1438 n_read += n_available;
1439 size -= n_available;
1440 }
1441 }
6fe692e9 1442
b5cb4464 1443 return n_read;
6fe692e9 1444}
693758d5 1445#undef FUNC_NAME
6fe692e9
MD
1446
1447/* scm_c_write
1448 *
1449 * Used by an application to write arbitrary number of bytes to an SCM
1450 * port. Similar semantics as libc write. However, unlike libc
1451 * write, scm_c_write writes the requested number of bytes and has no
1452 * return value.
1453 *
1454 * Warning: Doesn't update port line and column counts!
1455 */
1456
693758d5 1457void
1be6b49c 1458scm_c_write (SCM port, const void *ptr, size_t size)
693758d5 1459#define FUNC_NAME "scm_c_write"
6fe692e9 1460{
693758d5
LC
1461 scm_t_port *pt;
1462 scm_t_ptob_descriptor *ptob;
1463
1464 SCM_VALIDATE_OPOUTPORT (1, port);
1465
1466 pt = SCM_PTAB_ENTRY (port);
1467 ptob = &scm_ptobs[SCM_PTOBNUM (port)];
6fe692e9
MD
1468
1469 if (pt->rw_active == SCM_PORT_READ)
1470 scm_end_input (port);
1471
1472 ptob->write (port, ptr, size);
1473
1474 if (pt->rw_random)
1475 pt->rw_active = SCM_PORT_WRITE;
1476}
693758d5 1477#undef FUNC_NAME
3cb988bd 1478
fca43887 1479void
a284e297 1480scm_flush (SCM port)
ee149d03 1481{
c014a02e 1482 long i = SCM_PTOBNUM (port);
7f2a6c38 1483 assert (i >= 0);
affc96b5 1484 (scm_ptobs[i].flush) (port);
ee149d03
JB
1485}
1486
283a1a0e 1487void
a284e297 1488scm_end_input (SCM port)
283a1a0e 1489{
c014a02e 1490 long offset;
92c2555f 1491 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e
GH
1492
1493 if (pt->read_buf == pt->putback_buf)
1494 {
1495 offset = pt->read_end - pt->read_pos;
1496 pt->read_buf = pt->saved_read_buf;
1497 pt->read_pos = pt->saved_read_pos;
1498 pt->read_end = pt->saved_read_end;
1499 pt->read_buf_size = pt->saved_read_buf_size;
1500 }
1501 else
1502 offset = 0;
1503
affc96b5 1504 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
1505}
1506
ee149d03
JB
1507\f
1508
1509
1510void
889975e5
MG
1511scm_unget_byte (int c, SCM port)
1512#define FUNC_NAME "scm_unget_byte"
ee149d03 1513{
92c2555f 1514 scm_t_port *pt = SCM_PTAB_ENTRY (port);
840ae05d 1515
6c951427
GH
1516 if (pt->read_buf == pt->putback_buf)
1517 /* already using the put-back buffer. */
1518 {
1519 /* enlarge putback_buf if necessary. */
1520 if (pt->read_end == pt->read_buf + pt->read_buf_size
1521 && pt->read_buf == pt->read_pos)
1522 {
1be6b49c 1523 size_t new_size = pt->read_buf_size * 2;
c6c79933 1524 unsigned char *tmp = (unsigned char *)
4c9419ac
MV
1525 scm_gc_realloc (pt->putback_buf, pt->read_buf_size, new_size,
1526 "putback buffer");
6c951427 1527
6c951427
GH
1528 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
1529 pt->read_end = pt->read_buf + pt->read_buf_size;
1530 pt->read_buf_size = pt->putback_buf_size = new_size;
1531 }
1532
1533 /* shift any existing bytes to buffer + 1. */
1534 if (pt->read_pos == pt->read_end)
1535 pt->read_end = pt->read_buf + 1;
1536 else if (pt->read_pos != pt->read_buf + 1)
1537 {
1538 int count = pt->read_end - pt->read_pos;
1539
1540 memmove (pt->read_buf + 1, pt->read_pos, count);
1541 pt->read_end = pt->read_buf + 1 + count;
1542 }
1543
1544 pt->read_pos = pt->read_buf;
1545 }
1546 else
1547 /* switch to the put-back buffer. */
1548 {
1549 if (pt->putback_buf == NULL)
1550 {
c357d546 1551 pt->putback_buf
92d8fd32
LC
1552 = (unsigned char *) scm_gc_malloc_pointerless
1553 (SCM_INITIAL_PUTBACK_BUF_SIZE, "putback buffer");
6c951427
GH
1554 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
1555 }
1556
1557 pt->saved_read_buf = pt->read_buf;
1558 pt->saved_read_pos = pt->read_pos;
1559 pt->saved_read_end = pt->read_end;
1560 pt->saved_read_buf_size = pt->read_buf_size;
1561
1562 pt->read_pos = pt->read_buf = pt->putback_buf;
1563 pt->read_end = pt->read_buf + 1;
1564 pt->read_buf_size = pt->putback_buf_size;
1565 }
1566
1567 *pt->read_buf = c;
ee149d03 1568
840ae05d
JB
1569 if (pt->rw_random)
1570 pt->rw_active = SCM_PORT_READ;
889975e5
MG
1571}
1572#undef FUNC_NAME
1573
63479112 1574void
889975e5
MG
1575scm_ungetc (scm_t_wchar c, SCM port)
1576#define FUNC_NAME "scm_ungetc"
1577{
1578 scm_t_port *pt = SCM_PTAB_ENTRY (port);
63479112
LC
1579 char *result;
1580 char result_buf[10];
1581 const char *encoding;
889975e5
MG
1582 size_t len;
1583 int i;
1584
63479112
LC
1585 if (pt->encoding != NULL)
1586 encoding = pt->encoding;
1587 else
1588 encoding = "ISO-8859-1";
1589
1590 len = sizeof (result_buf);
1591 result = u32_conv_to_encoding (encoding,
1592 (enum iconv_ilseq_handler) pt->ilseq_handler,
1593 (uint32_t *) &c, 1, NULL,
1594 result_buf, &len);
1595
1596 if (SCM_UNLIKELY (result == NULL || len == 0))
1597 {
1598 SCM chr;
1599
1600 chr = scm_integer_to_char (scm_from_uint32 (c));
1601 scm_encoding_error (FUNC_NAME, errno,
1602 "conversion to port encoding failed",
1603 "UTF-32", encoding,
1604 scm_string (scm_list_1 (chr)));
1605 }
1606
889975e5 1607 for (i = len - 1; i >= 0; i--)
63479112
LC
1608 scm_unget_byte (result[i], port);
1609
1610 if (SCM_UNLIKELY (result != result_buf))
1611 free (result);
840ae05d 1612
ee149d03
JB
1613 if (c == '\n')
1614 {
1615 /* What should col be in this case?
1616 * We'll leave it at -1.
1617 */
1618 SCM_LINUM (port) -= 1;
1619 }
1620 else
1621 SCM_COL(port) -= 1;
1622}
c6c79933 1623#undef FUNC_NAME
ee149d03
JB
1624
1625
1626void
70d63753 1627scm_ungets (const char *s, int n, SCM port)
ee149d03
JB
1628{
1629 /* This is simple minded and inefficient, but unreading strings is
1630 * probably not a common operation, and remember that line and
1631 * column numbers have to be handled...
1632 *
1633 * Please feel free to write an optimized version!
1634 */
1635 while (n--)
1636 scm_ungetc (s[n], port);
1637}
1638
1639
3b3b36dd 1640SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1bbd0b84 1641 (SCM port),
1e6808ea
MG
1642 "Return the next character available from @var{port},\n"
1643 "@emph{without} updating @var{port} to point to the following\n"
1644 "character. If no more characters are available, the\n"
c2dfff19
KR
1645 "end-of-file object is returned.\n"
1646 "\n"
1647 "The value returned by\n"
1e6808ea
MG
1648 "a call to @code{peek-char} is the same as the value that would\n"
1649 "have been returned by a call to @code{read-char} on the same\n"
1650 "port. The only difference is that the very next call to\n"
1651 "@code{read-char} or @code{peek-char} on that @var{port} will\n"
1652 "return the value returned by the preceding call to\n"
1653 "@code{peek-char}. In particular, a call to @code{peek-char} on\n"
1654 "an interactive port will hang waiting for input whenever a call\n"
c2dfff19 1655 "to @code{read-char} would have hung.")
1bbd0b84 1656#define FUNC_NAME s_scm_peek_char
ee149d03 1657{
fd5eec2b
LC
1658 SCM result;
1659 scm_t_wchar c;
1660 char bytes[SCM_MBCHAR_BUF_SIZE];
1661 long column, line;
1662 size_t len;
1663
ee149d03 1664 if (SCM_UNBNDP (port))
9de87eea 1665 port = scm_current_input_port ();
b2456dd4 1666 SCM_VALIDATE_OPINPORT (1, port);
fd5eec2b
LC
1667
1668 column = SCM_COL (port);
1669 line = SCM_LINUM (port);
1670
1671 c = get_codepoint (port, bytes, &len);
1672 if (c == EOF)
1673 result = SCM_EOF_VAL;
1674 else
1675 {
1676 long i;
1677
1678 result = SCM_MAKE_CHAR (c);
1679
1680 for (i = len - 1; i >= 0; i--)
1681 scm_unget_byte (bytes[i], port);
1682
1683 SCM_COL (port) = column;
1684 SCM_LINUM (port) = line;
1685 }
1686
1687 return result;
3cb988bd 1688}
1bbd0b84 1689#undef FUNC_NAME
3cb988bd 1690
1be4270a 1691SCM_DEFINE (scm_unread_char, "unread-char", 1, 1, 0,
1bbd0b84 1692 (SCM cobj, SCM port),
b380b885
MD
1693 "Place @var{char} in @var{port} so that it will be read by the\n"
1694 "next read operation. If called multiple times, the unread characters\n"
1695 "will be read again in last-in first-out order. If @var{port} is\n"
1696 "not supplied, the current input port is used.")
1bbd0b84 1697#define FUNC_NAME s_scm_unread_char
0f2d19dd
JB
1698{
1699 int c;
1700
34d19ef6 1701 SCM_VALIDATE_CHAR (1, cobj);
0f2d19dd 1702 if (SCM_UNBNDP (port))
9de87eea 1703 port = scm_current_input_port ();
b2456dd4 1704 SCM_VALIDATE_OPINPORT (2, port);
0f2d19dd 1705
7866a09b 1706 c = SCM_CHAR (cobj);
0f2d19dd 1707
b7f3516f 1708 scm_ungetc (c, port);
0f2d19dd
JB
1709 return cobj;
1710}
1bbd0b84 1711#undef FUNC_NAME
0f2d19dd 1712
a1ec6916 1713SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1bbd0b84 1714 (SCM str, SCM port),
b380b885
MD
1715 "Place the string @var{str} in @var{port} so that its characters will be\n"
1716 "read in subsequent read operations. If called multiple times, the\n"
1717 "unread characters will be read again in last-in first-out order. If\n"
1718 "@var{port} is not supplied, the current-input-port is used.")
1bbd0b84 1719#define FUNC_NAME s_scm_unread_string
ee1e7e13 1720{
889975e5 1721 int n;
34d19ef6 1722 SCM_VALIDATE_STRING (1, str);
ee1e7e13 1723 if (SCM_UNBNDP (port))
9de87eea 1724 port = scm_current_input_port ();
b2456dd4 1725 SCM_VALIDATE_OPINPORT (2, port);
ee1e7e13 1726
889975e5
MG
1727 n = scm_i_string_length (str);
1728
1729 while (n--)
1730 scm_ungetc (scm_i_string_ref (str, n), port);
ee1e7e13
MD
1731
1732 return str;
1733}
1bbd0b84 1734#undef FUNC_NAME
ee1e7e13 1735
a1ec6916 1736SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1e6808ea
MG
1737 (SCM fd_port, SCM offset, SCM whence),
1738 "Sets the current position of @var{fd/port} to the integer\n"
1739 "@var{offset}, which is interpreted according to the value of\n"
1740 "@var{whence}.\n"
1741 "\n"
1742 "One of the following variables should be supplied for\n"
1743 "@var{whence}:\n"
b380b885
MD
1744 "@defvar SEEK_SET\n"
1745 "Seek from the beginning of the file.\n"
1746 "@end defvar\n"
1747 "@defvar SEEK_CUR\n"
1748 "Seek from the current position.\n"
1749 "@end defvar\n"
1750 "@defvar SEEK_END\n"
1751 "Seek from the end of the file.\n"
1e6808ea
MG
1752 "@end defvar\n"
1753 "If @var{fd/port} is a file descriptor, the underlying system\n"
1754 "call is @code{lseek}. @var{port} may be a string port.\n"
1755 "\n"
1756 "The value returned is the new position in the file. This means\n"
1757 "that the current position of a port can be obtained using:\n"
1758 "@lisp\n"
b380b885 1759 "(seek port 0 SEEK_CUR)\n"
1e6808ea 1760 "@end lisp")
1bbd0b84 1761#define FUNC_NAME s_scm_seek
840ae05d 1762{
840ae05d
JB
1763 int how;
1764
1e6808ea 1765 fd_port = SCM_COERCE_OUTPORT (fd_port);
840ae05d 1766
a55c2b68 1767 how = scm_to_int (whence);
840ae05d 1768 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1bbd0b84 1769 SCM_OUT_OF_RANGE (3, whence);
23f2b9a3 1770
0a94eb00 1771 if (SCM_OPPORTP (fd_port))
840ae05d 1772 {
92c2555f 1773 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (fd_port);
f1ce9199
LC
1774 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1775 off_t_or_off64_t rv;
840ae05d
JB
1776
1777 if (!ptob->seek)
1bbd0b84 1778 SCM_MISC_ERROR ("port is not seekable",
1e6808ea 1779 scm_cons (fd_port, SCM_EOL));
840ae05d 1780 else
1e6808ea 1781 rv = ptob->seek (fd_port, off, how);
f1ce9199 1782 return scm_from_off_t_or_off64_t (rv);
840ae05d
JB
1783 }
1784 else /* file descriptor?. */
1785 {
23f2b9a3
KR
1786 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1787 off_t_or_off64_t rv;
1788 rv = lseek_or_lseek64 (scm_to_int (fd_port), off, how);
840ae05d 1789 if (rv == -1)
1bbd0b84 1790 SCM_SYSERROR;
23f2b9a3 1791 return scm_from_off_t_or_off64_t (rv);
840ae05d 1792 }
840ae05d 1793}
1bbd0b84 1794#undef FUNC_NAME
840ae05d 1795
8ab3d8a0
KR
1796#ifndef O_BINARY
1797#define O_BINARY 0
1798#endif
1799
1800/* Mingw has ftruncate(), perhaps implemented above using chsize, but
1801 doesn't have the filename version truncate(), hence this code. */
1802#if HAVE_FTRUNCATE && ! HAVE_TRUNCATE
1803static int
1804truncate (const char *file, off_t length)
82893676 1805{
8ab3d8a0
KR
1806 int ret, fdes;
1807
1808 fdes = open (file, O_BINARY | O_WRONLY);
1809 if (fdes == -1)
1810 return -1;
1811
1812 ret = ftruncate (fdes, length);
1813 if (ret == -1)
82893676 1814 {
8ab3d8a0 1815 int save_errno = errno;
82893676 1816 close (fdes);
8ab3d8a0
KR
1817 errno = save_errno;
1818 return -1;
82893676 1819 }
8ab3d8a0
KR
1820
1821 return close (fdes);
82893676 1822}
8ab3d8a0 1823#endif /* HAVE_FTRUNCATE && ! HAVE_TRUNCATE */
82893676 1824
a1ec6916 1825SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1bbd0b84 1826 (SCM object, SCM length),
8ab3d8a0
KR
1827 "Truncate @var{file} to @var{length} bytes. @var{file} can be a\n"
1828 "filename string, a port object, or an integer file descriptor.\n"
1829 "The return value is unspecified.\n"
1830 "\n"
1831 "For a port or file descriptor @var{length} can be omitted, in\n"
1832 "which case the file is truncated at the current position (per\n"
1833 "@code{ftell} above).\n"
1834 "\n"
1835 "On most systems a file can be extended by giving a length\n"
1836 "greater than the current size, but this is not mandatory in the\n"
1837 "POSIX standard.")
1bbd0b84 1838#define FUNC_NAME s_scm_truncate_file
840ae05d 1839{
69bc9ff3 1840 int rv;
69bc9ff3 1841
2b829bbb
KR
1842 /* "object" can be a port, fdes or filename.
1843
1844 Negative "length" makes no sense, but it's left to truncate() or
1845 ftruncate() to give back an error for that (normally EINVAL).
1846 */
840ae05d 1847
840ae05d
JB
1848 if (SCM_UNBNDP (length))
1849 {
69bc9ff3 1850 /* must supply length if object is a filename. */
7f9994d9 1851 if (scm_is_string (object))
34d19ef6 1852 SCM_MISC_ERROR("must supply length if OBJECT is a filename", SCM_EOL);
69bc9ff3 1853
e11e83f3 1854 length = scm_seek (object, SCM_INUM0, scm_from_int (SEEK_CUR));
840ae05d 1855 }
3fe6190f 1856
69bc9ff3 1857 object = SCM_COERCE_OUTPORT (object);
e11e83f3 1858 if (scm_is_integer (object))
69bc9ff3 1859 {
23f2b9a3
KR
1860 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
1861 SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
1862 c_length));
69bc9ff3 1863 }
0c95b57d 1864 else if (SCM_OPOUTPORTP (object))
69bc9ff3 1865 {
f1ce9199 1866 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
92c2555f
MV
1867 scm_t_port *pt = SCM_PTAB_ENTRY (object);
1868 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1869
affc96b5 1870 if (!ptob->truncate)
1bbd0b84 1871 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1872 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1873 scm_end_input (object);
69bc9ff3 1874 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1875 ptob->flush (object);
69bc9ff3 1876
affc96b5 1877 ptob->truncate (object, c_length);
69bc9ff3
GH
1878 rv = 0;
1879 }
1880 else
1881 {
2b829bbb 1882 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
7f9994d9
MV
1883 char *str = scm_to_locale_string (object);
1884 int eno;
2b829bbb 1885 SCM_SYSCALL (rv = truncate_or_truncate64 (str, c_length));
7f9994d9
MV
1886 eno = errno;
1887 free (str);
1888 errno = eno;
69bc9ff3
GH
1889 }
1890 if (rv == -1)
1bbd0b84 1891 SCM_SYSERROR;
840ae05d
JB
1892 return SCM_UNSPECIFIED;
1893}
1bbd0b84 1894#undef FUNC_NAME
840ae05d 1895
a1ec6916 1896SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1bbd0b84 1897 (SCM port),
a150979d
KR
1898 "Return the current line number for @var{port}.\n"
1899 "\n"
1900 "The first line of a file is 0. But you might want to add 1\n"
1901 "when printing line numbers, since starting from 1 is\n"
1902 "traditional in error messages, and likely to be more natural to\n"
1903 "non-programmers.")
1bbd0b84 1904#define FUNC_NAME s_scm_port_line
0f2d19dd 1905{
78446828 1906 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1907 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1908 return scm_from_long (SCM_LINUM (port));
0f2d19dd 1909}
1bbd0b84 1910#undef FUNC_NAME
0f2d19dd 1911
a1ec6916 1912SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1bbd0b84 1913 (SCM port, SCM line),
a150979d
KR
1914 "Set the current line number for @var{port} to @var{line}. The\n"
1915 "first line of a file is 0.")
1bbd0b84 1916#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1917{
360fc44c 1918 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1919 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1920 SCM_PTAB_ENTRY (port)->line_number = scm_to_long (line);
564478fd 1921 return SCM_UNSPECIFIED;
d043d8c2 1922}
1bbd0b84 1923#undef FUNC_NAME
d043d8c2 1924
a1ec6916 1925SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1bbd0b84 1926 (SCM port),
a150979d
KR
1927 "Return the current column number of @var{port}.\n"
1928 "If the number is\n"
b380b885
MD
1929 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1930 "- i.e. the first character of the first line is line 0, column 0.\n"
1931 "(However, when you display a file position, for example in an error\n"
650a1cf9 1932 "message, we recommend you add 1 to get 1-origin integers. This is\n"
b380b885
MD
1933 "because lines and column numbers traditionally start with 1, and that is\n"
1934 "what non-programmers will find most natural.)")
1bbd0b84 1935#define FUNC_NAME s_scm_port_column
0f2d19dd 1936{
78446828 1937 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1938 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 1939 return scm_from_int (SCM_COL (port));
0f2d19dd 1940}
1bbd0b84 1941#undef FUNC_NAME
0f2d19dd 1942
a1ec6916 1943SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1bbd0b84 1944 (SCM port, SCM column),
a150979d
KR
1945 "Set the current column of @var{port}. Before reading the first\n"
1946 "character on a line the column should be 0.")
1bbd0b84 1947#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1948{
360fc44c 1949 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1950 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 1951 SCM_PTAB_ENTRY (port)->column_number = scm_to_int (column);
564478fd 1952 return SCM_UNSPECIFIED;
d043d8c2 1953}
1bbd0b84 1954#undef FUNC_NAME
d043d8c2 1955
a1ec6916 1956SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1bbd0b84 1957 (SCM port),
b380b885 1958 "Return the filename associated with @var{port}. This function returns\n"
2a2a730b 1959 "the strings \"standard input\", \"standard output\" and \"standard error\"\n"
a3c8b9fc 1960 "when called on the current input, output and error ports respectively.")
1bbd0b84 1961#define FUNC_NAME s_scm_port_filename
0f2d19dd 1962{
78446828 1963 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1964 SCM_VALIDATE_OPENPORT (1, port);
b24b5e13 1965 return SCM_FILENAME (port);
0f2d19dd 1966}
1bbd0b84 1967#undef FUNC_NAME
0f2d19dd 1968
a1ec6916 1969SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1bbd0b84 1970 (SCM port, SCM filename),
b380b885
MD
1971 "Change the filename associated with @var{port}, using the current input\n"
1972 "port if none is specified. Note that this does not change the port's\n"
1973 "source of data, but only the value that is returned by\n"
1974 "@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1975#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1976{
360fc44c 1977 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1978 SCM_VALIDATE_OPENPORT (1, port);
360fc44c 1979 /* We allow the user to set the filename to whatever he likes. */
b24b5e13
DH
1980 SCM_SET_FILENAME (port, filename);
1981 return SCM_UNSPECIFIED;
d14af9f2 1982}
1bbd0b84 1983#undef FUNC_NAME
d14af9f2 1984
d6a6989e
LC
1985/* A fluid specifying the default encoding for newly created ports. If it is
1986 a string, that is the encoding. If it is #f, it is in the "native"
1987 (Latin-1) encoding. */
1988SCM_VARIABLE (default_port_encoding_var, "%default-port-encoding");
1989
889975e5
MG
1990static int scm_port_encoding_init = 0;
1991
1992/* Return a C string representation of the current encoding. */
1993const char *
1994scm_i_get_port_encoding (SCM port)
1995{
1996 SCM encoding;
1997
1998 if (scm_is_false (port))
1999 {
2000 if (!scm_port_encoding_init)
2001 return NULL;
d6a6989e 2002 else if (!scm_is_fluid (SCM_VARIABLE_REF (default_port_encoding_var)))
889975e5
MG
2003 return NULL;
2004 else
2005 {
d6a6989e 2006 encoding = scm_fluid_ref (SCM_VARIABLE_REF (default_port_encoding_var));
889975e5
MG
2007 if (!scm_is_string (encoding))
2008 return NULL;
2009 else
2010 return scm_i_string_chars (encoding);
2011 }
2012 }
2013 else
2014 {
2015 scm_t_port *pt;
2016 pt = SCM_PTAB_ENTRY (port);
2017 if (pt->encoding)
2018 return pt->encoding;
2019 else
2020 return NULL;
2021 }
2022}
2023
b77afe82 2024/* Returns ENC if it is a recognized encoding. If it isn't, it tries
889975e5
MG
2025 to find an alias of ENC that is valid. Otherwise, it returns
2026 NULL. */
2027static const char *
2028find_valid_encoding (const char *enc)
2029{
2030 int isvalid = 0;
2031 const char str[] = " ";
63479112 2032 scm_t_uint32 result_buf;
889975e5
MG
2033 scm_t_uint32 *u32;
2034 size_t u32len;
63479112
LC
2035
2036 u32len = sizeof (result_buf) / sizeof (scm_t_uint32);
889975e5 2037 u32 = u32_conv_from_encoding (enc, iconveh_error, str, 1,
63479112 2038 NULL, &result_buf, &u32len);
889975e5 2039 isvalid = (u32 != NULL);
63479112
LC
2040
2041 if (SCM_UNLIKELY (u32 != &result_buf))
2042 free (u32);
2043
889975e5
MG
2044 if (isvalid)
2045 return enc;
2046
2047 return NULL;
2048}
2049
2050void
2051scm_i_set_port_encoding_x (SCM port, const char *enc)
2052{
2053 const char *valid_enc;
2054 scm_t_port *pt;
2055
2056 /* Null is shorthand for the native, Latin-1 encoding. */
2057 if (enc == NULL)
2058 valid_enc = NULL;
2059 else
2060 {
2061 valid_enc = find_valid_encoding (enc);
2062 if (valid_enc == NULL)
2063 {
2064 SCM err;
2065 err = scm_from_locale_string (enc);
2066 scm_misc_error (NULL, "invalid or unknown character encoding ~s",
2067 scm_list_1 (err));
2068 }
2069 }
2070
2071 if (scm_is_false (port))
2072 {
2073 /* Set the default encoding for future ports. */
2074 if (!scm_port_encoding_init
d6a6989e 2075 || !scm_is_fluid (SCM_VARIABLE_REF (default_port_encoding_var)))
889975e5
MG
2076 scm_misc_error (NULL, "tried to set port encoding fluid before it is initialized",
2077 SCM_EOL);
2078
2079 if (valid_enc == NULL
2080 || !strcmp (valid_enc, "ASCII")
2081 || !strcmp (valid_enc, "ANSI_X3.4-1968")
2082 || !strcmp (valid_enc, "ISO-8859-1"))
d6a6989e 2083 scm_fluid_set_x (SCM_VARIABLE_REF (default_port_encoding_var), SCM_BOOL_F);
889975e5 2084 else
d6a6989e 2085 scm_fluid_set_x (SCM_VARIABLE_REF (default_port_encoding_var),
889975e5
MG
2086 scm_from_locale_string (valid_enc));
2087 }
2088 else
2089 {
2090 /* Set the character encoding for this port. */
2091 pt = SCM_PTAB_ENTRY (port);
889975e5
MG
2092 if (valid_enc == NULL)
2093 pt->encoding = NULL;
2094 else
682d78d0 2095 pt->encoding = scm_gc_strdup (valid_enc, "port");
889975e5
MG
2096 }
2097}
2098
2099SCM_DEFINE (scm_port_encoding, "port-encoding", 1, 0, 0,
2100 (SCM port),
2101 "Returns, as a string, the character encoding that @var{port}\n"
2102 "uses to interpret its input and output.\n")
2103#define FUNC_NAME s_scm_port_encoding
2104{
2105 scm_t_port *pt;
2106 const char *enc;
2107
2108 SCM_VALIDATE_PORT (1, port);
2109
2110 pt = SCM_PTAB_ENTRY (port);
2111 enc = scm_i_get_port_encoding (port);
2112 if (enc)
2113 return scm_from_locale_string (pt->encoding);
2114 else
0af34a3f 2115 return SCM_BOOL_F;
889975e5
MG
2116}
2117#undef FUNC_NAME
d6a6989e 2118
889975e5
MG
2119SCM_DEFINE (scm_set_port_encoding_x, "set-port-encoding!", 2, 0, 0,
2120 (SCM port, SCM enc),
2121 "Sets the character encoding that will be used to interpret all\n"
2122 "port I/O. New ports are created with the encoding\n"
2123 "appropriate for the current locale if @code{setlocale} has \n"
2124 "been called or ISO-8859-1 otherwise\n"
2125 "and this procedure can be used to modify that encoding.\n")
889975e5
MG
2126#define FUNC_NAME s_scm_set_port_encoding_x
2127{
2128 char *enc_str;
2129 const char *valid_enc_str;
2130
2131 SCM_VALIDATE_PORT (1, port);
2132 SCM_VALIDATE_STRING (2, enc);
2133
2134 enc_str = scm_to_locale_string (enc);
2135 valid_enc_str = find_valid_encoding (enc_str);
2136 if (valid_enc_str == NULL)
2137 {
2138 free (enc_str);
2139 scm_misc_error (FUNC_NAME, "invalid or unknown character encoding ~s",
2140 scm_list_1 (enc));
2141 }
2142 else
2143 {
2144 scm_i_set_port_encoding_x (port, valid_enc_str);
2145 free (enc_str);
2146 }
2147 return SCM_UNSPECIFIED;
2148}
2149#undef FUNC_NAME
2150
2151
2152/* This determines how conversions handle unconvertible characters. */
2153SCM_GLOBAL_VARIABLE (scm_conversion_strategy, "%port-conversion-strategy");
2154static int scm_conversion_strategy_init = 0;
2155
2156scm_t_string_failed_conversion_handler
2157scm_i_get_conversion_strategy (SCM port)
2158{
2159 SCM encoding;
2160
2161 if (scm_is_false (port))
2162 {
2163 if (!scm_conversion_strategy_init
2164 || !scm_is_fluid (SCM_VARIABLE_REF (scm_conversion_strategy)))
2165 return SCM_FAILED_CONVERSION_QUESTION_MARK;
2166 else
2167 {
2168 encoding = scm_fluid_ref (SCM_VARIABLE_REF (scm_conversion_strategy));
2169 if (scm_is_false (encoding))
2170 return SCM_FAILED_CONVERSION_QUESTION_MARK;
2171 else
2172 return (scm_t_string_failed_conversion_handler) scm_to_int (encoding);
2173 }
2174 }
2175 else
2176 {
2177 scm_t_port *pt;
2178 pt = SCM_PTAB_ENTRY (port);
e1ee45e7 2179 return pt->ilseq_handler;
889975e5
MG
2180 }
2181
2182}
2183
2184void
2185scm_i_set_conversion_strategy_x (SCM port,
2186 scm_t_string_failed_conversion_handler handler)
2187{
2188 SCM strategy;
2189 scm_t_port *pt;
2190
2191 strategy = scm_from_int ((int) handler);
2192
2193 if (scm_is_false (port))
2194 {
2195 /* Set the default encoding for future ports. */
2196 if (!scm_conversion_strategy
2197 || !scm_is_fluid (SCM_VARIABLE_REF (scm_conversion_strategy)))
2198 scm_misc_error (NULL, "tried to set conversion strategy fluid before it is initialized",
2199 SCM_EOL);
2200 scm_fluid_set_x (SCM_VARIABLE_REF (scm_conversion_strategy), strategy);
2201 }
2202 else
2203 {
2204 /* Set the character encoding for this port. */
2205 pt = SCM_PTAB_ENTRY (port);
2206 pt->ilseq_handler = handler;
2207 }
2208}
2209
2210SCM_DEFINE (scm_port_conversion_strategy, "port-conversion-strategy",
2211 1, 0, 0, (SCM port),
2212 "Returns the behavior of the port when handling a character that\n"
2213 "is not representable in the port's current encoding.\n"
2214 "It returns the symbol @code{error} if unrepresentable characters\n"
2215 "should cause exceptions, @code{substitute} if the port should\n"
2216 "try to replace unrepresentable characters with question marks or\n"
2217 "approximate characters, or @code{escape} if unrepresentable\n"
2218 "characters should be converted to string escapes.\n"
2219 "\n"
2220 "If @var{port} is @code{#f}, then the current default behavior\n"
2221 "will be returned. New ports will have this default behavior\n"
2222 "when they are created.\n")
2223#define FUNC_NAME s_scm_port_conversion_strategy
2224{
2225 scm_t_string_failed_conversion_handler h;
2226
2227 SCM_VALIDATE_OPPORT (1, port);
2228
2229 if (!scm_is_false (port))
2230 {
2231 SCM_VALIDATE_OPPORT (1, port);
2232 }
2233
2234 h = scm_i_get_conversion_strategy (port);
2235 if (h == SCM_FAILED_CONVERSION_ERROR)
2236 return scm_from_locale_symbol ("error");
2237 else if (h == SCM_FAILED_CONVERSION_QUESTION_MARK)
2238 return scm_from_locale_symbol ("substitute");
2239 else if (h == SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE)
2240 return scm_from_locale_symbol ("escape");
2241 else
2242 abort ();
2243
2244 /* Never gets here. */
2245 return SCM_UNDEFINED;
2246}
2247#undef FUNC_NAME
2248
2249SCM_DEFINE (scm_set_port_conversion_strategy_x, "set-port-conversion-strategy!",
2250 2, 0, 0,
2251 (SCM port, SCM sym),
2252 "Sets the behavior of the interpreter when outputting a character\n"
2253 "that is not representable in the port's current encoding.\n"
2254 "@var{sym} can be either @code{'error}, @code{'substitute}, or\n"
2255 "@code{'escape}. If it is @code{'error}, an error will be thrown\n"
2256 "when an unconvertible character is encountered. If it is\n"
2257 "@code{'substitute}, then unconvertible characters will \n"
2258 "be replaced with approximate characters, or with question marks\n"
2259 "if no approximately correct character is available.\n"
2260 "If it is @code{'escape},\n"
2261 "it will appear as a hex escape when output.\n"
2262 "\n"
2263 "If @var{port} is an open port, the conversion error behavior\n"
2264 "is set for that port. If it is @code{#f}, it is set as the\n"
2265 "default behavior for any future ports that get created in\n"
2266 "this thread.\n")
2267#define FUNC_NAME s_scm_set_port_conversion_strategy_x
2268{
2269 SCM err;
2270 SCM qm;
2271 SCM esc;
2272
2273 if (!scm_is_false (port))
2274 {
2275 SCM_VALIDATE_OPPORT (1, port);
2276 }
2277
2278 err = scm_from_locale_symbol ("error");
2279 if (scm_is_true (scm_eqv_p (sym, err)))
2280 {
2281 scm_i_set_conversion_strategy_x (port, SCM_FAILED_CONVERSION_ERROR);
2282 return SCM_UNSPECIFIED;
2283 }
2284
2285 qm = scm_from_locale_symbol ("substitute");
2286 if (scm_is_true (scm_eqv_p (sym, qm)))
2287 {
2288 scm_i_set_conversion_strategy_x (port,
2289 SCM_FAILED_CONVERSION_QUESTION_MARK);
2290 return SCM_UNSPECIFIED;
2291 }
2292
2293 esc = scm_from_locale_symbol ("escape");
2294 if (scm_is_true (scm_eqv_p (sym, esc)))
2295 {
2296 scm_i_set_conversion_strategy_x (port,
2297 SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE);
2298 return SCM_UNSPECIFIED;
2299 }
2300
2301 SCM_MISC_ERROR ("unknown conversion behavior ~s", scm_list_1 (sym));
2302
2303 return SCM_UNSPECIFIED;
2304}
2305#undef FUNC_NAME
2306
2307
2308
f12733c9
MD
2309void
2310scm_print_port_mode (SCM exp, SCM port)
2311{
2312 scm_puts (SCM_CLOSEDP (exp)
2313 ? "closed: "
f9a64404
DH
2314 : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
2315 ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
2316 ? "input-output: "
2317 : "input: ")
f9a64404 2318 : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
2319 ? "output: "
2320 : "bogus: ")),
2321 port);
2322}
1cc91f1b 2323
f12733c9 2324int
e81d98ec 2325scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 2326{
f12733c9
MD
2327 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
2328 if (!type)
2329 type = "port";
b7f3516f 2330 scm_puts ("#<", port);
f12733c9 2331 scm_print_port_mode (exp, port);
b7f3516f
TT
2332 scm_puts (type, port);
2333 scm_putc (' ', port);
0345e278 2334 scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
b7f3516f 2335 scm_putc ('>', port);
f12733c9 2336 return 1;
0f2d19dd
JB
2337}
2338
0f2d19dd 2339\f
ee149d03 2340
d68fee48 2341/* Void ports. */
0f2d19dd 2342
92c2555f 2343scm_t_bits scm_tc16_void_port = 0;
0f2d19dd 2344
e81d98ec 2345static int fill_input_void_port (SCM port SCM_UNUSED)
283a1a0e 2346{
70df8af6 2347 return EOF;
283a1a0e
GH
2348}
2349
31703ab8 2350static void
e81d98ec
DH
2351write_void_port (SCM port SCM_UNUSED,
2352 const void *data SCM_UNUSED,
2353 size_t size SCM_UNUSED)
31703ab8
GH
2354{
2355}
2356
d617ee18
MV
2357static SCM
2358scm_i_void_port (long mode_bits)
0f2d19dd 2359{
9de87eea 2360 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
402788a9 2361 {
da220f27
HWN
2362 SCM answer = scm_new_port_table_entry (scm_tc16_void_port);
2363 scm_t_port * pt = SCM_PTAB_ENTRY(answer);
2364
402788a9 2365 scm_port_non_buffer (pt);
402788a9
HWN
2366
2367 SCM_SETSTREAM (answer, 0);
2368 SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
9de87eea 2369 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
402788a9
HWN
2370 return answer;
2371 }
0f2d19dd
JB
2372}
2373
d617ee18
MV
2374SCM
2375scm_void_port (char *mode_str)
2376{
2377 return scm_i_void_port (scm_mode_bits (mode_str));
2378}
2379
a1ec6916 2380SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 2381 (SCM mode),
70df8af6 2382 "Create and return a new void port. A void port acts like\n"
bb2c02f2 2383 "@file{/dev/null}. The @var{mode} argument\n"
70df8af6 2384 "specifies the input/output modes for this port: see the\n"
b380b885 2385 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 2386#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 2387{
d617ee18 2388 return scm_i_void_port (scm_i_mode_bits (mode));
0f2d19dd 2389}
1bbd0b84 2390#undef FUNC_NAME
0f2d19dd 2391
0f2d19dd 2392\f
89545eba 2393/* Initialization. */
1cc91f1b 2394
0f2d19dd
JB
2395void
2396scm_init_ports ()
0f2d19dd 2397{
840ae05d 2398 /* lseek() symbols. */
e11e83f3
MV
2399 scm_c_define ("SEEK_SET", scm_from_int (SEEK_SET));
2400 scm_c_define ("SEEK_CUR", scm_from_int (SEEK_CUR));
2401 scm_c_define ("SEEK_END", scm_from_int (SEEK_END));
840ae05d 2402
70df8af6
GH
2403 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
2404 write_void_port);
9de87eea 2405
f39448c5
AW
2406 cur_inport_fluid = scm_make_fluid ();
2407 cur_outport_fluid = scm_make_fluid ();
2408 cur_errport_fluid = scm_make_fluid ();
2409 cur_loadport_fluid = scm_make_fluid ();
9de87eea 2410
f39448c5 2411 scm_i_port_weak_hash = scm_make_weak_key_hash_table (SCM_I_MAKINUM(31));
d6a6989e 2412
a0599745 2413#include "libguile/ports.x"
889975e5 2414
d6a6989e
LC
2415 /* Use Latin-1 as the default port encoding. */
2416 SCM_VARIABLE_SET (default_port_encoding_var, scm_make_fluid ());
2417 scm_fluid_set_x (SCM_VARIABLE_REF (default_port_encoding_var), SCM_BOOL_F);
889975e5 2418 scm_port_encoding_init = 1;
d6a6989e 2419
889975e5
MG
2420 SCM_VARIABLE_SET (scm_conversion_strategy, scm_make_fluid ());
2421 scm_fluid_set_x (SCM_VARIABLE_REF (scm_conversion_strategy),
2422 scm_from_int ((int) SCM_FAILED_CONVERSION_QUESTION_MARK));
2423 scm_conversion_strategy_init = 1;
2424
0f2d19dd 2425}
89e00824
ML
2426
2427/*
2428 Local Variables:
2429 c-file-style: "gnu"
2430 End:
2431*/