Make scm_c_read use caller buffer only for unbuffered ports.
[bpt/guile.git] / libguile / ports.c
CommitLineData
f5c2af4b 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
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
92205699 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd 19\f
d68fee48
JB
20/* Headers. */
21
2b829bbb
KR
22#define _LARGEFILE64_SOURCE /* ask for stat64 etc */
23
dbb605f5 24#ifdef HAVE_CONFIG_H
bd515f37
RB
25# include <config.h>
26#endif
27
0f2d19dd 28#include <stdio.h>
e6e2e95a 29#include <errno.h>
8ab3d8a0 30#include <fcntl.h> /* for chsize on mingw */
b5cb4464 31#include <assert.h>
e6e2e95a 32
a0599745 33#include "libguile/_scm.h"
4e047c3e 34#include "libguile/async.h"
f0942910 35#include "libguile/eval.h"
8ab3d8a0 36#include "libguile/fports.h" /* direct access for seek and truncate */
a0599745 37#include "libguile/objects.h"
9511876f 38#include "libguile/goops.h"
a0599745
MD
39#include "libguile/smob.h"
40#include "libguile/chars.h"
185e369a 41#include "libguile/dynwind.h"
0f2d19dd 42
a0599745 43#include "libguile/keywords.h"
5dbc6c06 44#include "libguile/hashtab.h"
a0599745
MD
45#include "libguile/root.h"
46#include "libguile/strings.h"
b42170a4 47#include "libguile/mallocs.h"
a0599745
MD
48#include "libguile/validate.h"
49#include "libguile/ports.h"
3a5fb14d 50#include "libguile/vectors.h"
5dbc6c06 51#include "libguile/weaks.h"
9de87eea 52#include "libguile/fluids.h"
0f2d19dd 53
bd9e24b3
GH
54#ifdef HAVE_STRING_H
55#include <string.h>
56#endif
57
0f2d19dd 58#ifdef HAVE_MALLOC_H
95b88819 59#include <malloc.h>
0f2d19dd
JB
60#endif
61
ec65f5da
MV
62#ifdef HAVE_IO_H
63#include <io.h>
64#endif
65
0f2d19dd
JB
66#ifdef HAVE_UNISTD_H
67#include <unistd.h>
68#endif
69
95b88819
GH
70#ifdef HAVE_SYS_IOCTL_H
71#include <sys/ioctl.h>
72#endif
d68fee48 73
8ab3d8a0
KR
74/* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize
75 already, but have this code here in case that wasn't so in past versions,
76 or perhaps to help other minimal DOS environments.
77
78 gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which
79 might be possibilities if we've got other systems without ftruncate. */
80
81#if HAVE_CHSIZE && ! HAVE_FTRUNCATE
82893676 82#define ftruncate(fd, size) chsize (fd, size)
8ab3d8a0
KR
83#undef HAVE_FTRUNCATE
84#define HAVE_FTRUNCATE 1
82893676
MG
85#endif
86
0f2d19dd 87\f
d68fee48 88/* The port kind table --- a dynamically resized array of port types. */
0f2d19dd
JB
89
90
91/* scm_ptobs scm_numptob
5dbc6c06 92 * implement a dynamically resized array of ptob records.
0f2d19dd
JB
93 * Indexes into this table are used when generating type
94 * tags for smobjects (if you know a tag you can get an index and conversely).
95 */
92c2555f 96scm_t_ptob_descriptor *scm_ptobs;
c014a02e 97long scm_numptob;
0f2d19dd 98
ee149d03 99/* GC marker for a port with stream of SCM type. */
0f2d19dd 100SCM
a284e297 101scm_markstream (SCM ptr)
0f2d19dd
JB
102{
103 int openp;
f9a64404 104 openp = SCM_CELL_WORD_0 (ptr) & SCM_OPN;
0f2d19dd 105 if (openp)
74a16888 106 return SCM_PACK (SCM_STREAM (ptr));
0f2d19dd
JB
107 else
108 return SCM_BOOL_F;
109}
110
f12733c9 111/*
f12733c9 112 * We choose to use an interface similar to the smob interface with
affc96b5 113 * fill_input and write as standard fields, passed to the port
f12733c9
MD
114 * type constructor, and optional fields set by setters.
115 */
116
70df8af6 117static void
e81d98ec 118flush_port_default (SCM port SCM_UNUSED)
70df8af6
GH
119{
120}
121
122static void
e81d98ec 123end_input_default (SCM port SCM_UNUSED, int offset SCM_UNUSED)
70df8af6
GH
124{
125}
0f2d19dd 126
4c9419ac
MV
127static size_t
128scm_port_free0 (SCM port)
129{
130 return 0;
131}
132
92c2555f 133scm_t_bits
f12733c9 134scm_make_port_type (char *name,
affc96b5 135 int (*fill_input) (SCM port),
8aa011a1 136 void (*write) (SCM port, const void *data, size_t size))
0f2d19dd
JB
137{
138 char *tmp;
139 if (255 <= scm_numptob)
140 goto ptoberr;
9de87eea 141 SCM_CRITICAL_SECTION_START;
f12733c9
MD
142 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
143 (1 + scm_numptob)
92c2555f 144 * sizeof (scm_t_ptob_descriptor)));
0f2d19dd
JB
145 if (tmp)
146 {
92c2555f 147 scm_ptobs = (scm_t_ptob_descriptor *) tmp;
affc96b5 148
f12733c9
MD
149 scm_ptobs[scm_numptob].name = name;
150 scm_ptobs[scm_numptob].mark = 0;
4c9419ac 151 scm_ptobs[scm_numptob].free = scm_port_free0;
f12733c9
MD
152 scm_ptobs[scm_numptob].print = scm_port_print;
153 scm_ptobs[scm_numptob].equalp = 0;
affc96b5
GH
154 scm_ptobs[scm_numptob].close = 0;
155
156 scm_ptobs[scm_numptob].write = write;
70df8af6 157 scm_ptobs[scm_numptob].flush = flush_port_default;
affc96b5 158
70df8af6 159 scm_ptobs[scm_numptob].end_input = end_input_default;
affc96b5
GH
160 scm_ptobs[scm_numptob].fill_input = fill_input;
161 scm_ptobs[scm_numptob].input_waiting = 0;
162
f12733c9 163 scm_ptobs[scm_numptob].seek = 0;
affc96b5
GH
164 scm_ptobs[scm_numptob].truncate = 0;
165
0f2d19dd
JB
166 scm_numptob++;
167 }
9de87eea 168 SCM_CRITICAL_SECTION_END;
0f2d19dd 169 if (!tmp)
2500356c
DH
170 {
171 ptoberr:
172 scm_memory_error ("scm_make_port_type");
173 }
f12733c9
MD
174 /* Make a class object if Goops is present */
175 if (scm_port_class)
176 scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
0f2d19dd
JB
177 return scm_tc7_port + (scm_numptob - 1) * 256;
178}
179
f12733c9 180void
23f2b9a3 181scm_set_port_mark (scm_t_bits tc, SCM (*mark) (SCM))
f12733c9
MD
182{
183 scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
184}
185
186void
23f2b9a3 187scm_set_port_free (scm_t_bits tc, size_t (*free) (SCM))
f12733c9
MD
188{
189 scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
190}
191
192void
23f2b9a3 193scm_set_port_print (scm_t_bits tc, int (*print) (SCM exp, SCM port,
f12733c9
MD
194 scm_print_state *pstate))
195{
196 scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
197}
198
199void
23f2b9a3 200scm_set_port_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
f12733c9
MD
201{
202 scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
203}
204
31703ab8 205void
23f2b9a3 206scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port))
31703ab8 207{
affc96b5 208 scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
31703ab8
GH
209}
210
f12733c9 211void
23f2b9a3 212scm_set_port_end_input (scm_t_bits tc, void (*end_input) (SCM port, int offset))
f12733c9 213{
affc96b5 214 scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
f12733c9
MD
215}
216
217void
23f2b9a3 218scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
f12733c9 219{
affc96b5 220 scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
f12733c9
MD
221}
222
223void
23f2b9a3 224scm_set_port_seek (scm_t_bits tc, off_t (*seek) (SCM port,
f12733c9
MD
225 off_t OFFSET,
226 int WHENCE))
227{
228 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
229}
230
231void
23f2b9a3 232scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM port, off_t length))
f12733c9 233{
affc96b5 234 scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
f12733c9
MD
235}
236
237void
23f2b9a3 238scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) (SCM))
f12733c9 239{
affc96b5 240 scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
f12733c9
MD
241}
242
0f2d19dd 243\f
0f2d19dd 244
3b3b36dd 245SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
1e6808ea
MG
246 (SCM port),
247 "Return @code{#t} if a character is ready on input @var{port}\n"
248 "and return @code{#f} otherwise. If @code{char-ready?} returns\n"
249 "@code{#t} then the next @code{read-char} operation on\n"
250 "@var{port} is guaranteed not to hang. If @var{port} is a file\n"
251 "port at end of file then @code{char-ready?} returns @code{#t}.\n"
c2dfff19
KR
252 "\n"
253 "@code{char-ready?} exists to make it possible for a\n"
1e6808ea
MG
254 "program to accept characters from interactive ports without\n"
255 "getting stuck waiting for input. Any input editors associated\n"
256 "with such ports must make sure that characters whose existence\n"
257 "has been asserted by @code{char-ready?} cannot be rubbed out.\n"
258 "If @code{char-ready?} were to return @code{#f} at end of file,\n"
259 "a port at end of file would be indistinguishable from an\n"
c2dfff19 260 "interactive port that has no ready characters.")
1bbd0b84 261#define FUNC_NAME s_scm_char_ready_p
0f2d19dd 262{
92c2555f 263 scm_t_port *pt;
6c951427 264
0f2d19dd 265 if (SCM_UNBNDP (port))
9de87eea 266 port = scm_current_input_port ();
0f2d19dd 267 else
34d19ef6 268 SCM_VALIDATE_OPINPORT (1, port);
d68fee48 269
ae4c4016
JB
270 pt = SCM_PTAB_ENTRY (port);
271
6c951427
GH
272 /* if the current read buffer is filled, or the
273 last pushed-back char has been read and the saved buffer is
274 filled, result is true. */
275 if (pt->read_pos < pt->read_end
276 || (pt->read_buf == pt->putback_buf
277 && pt->saved_read_pos < pt->saved_read_end))
0f2d19dd 278 return SCM_BOOL_T;
ee149d03
JB
279 else
280 {
92c2555f 281 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
ee149d03 282
affc96b5 283 if (ptob->input_waiting)
7888309b 284 return scm_from_bool(ptob->input_waiting (port));
ee149d03 285 else
6c951427 286 return SCM_BOOL_T;
ee149d03 287 }
0f2d19dd 288}
1bbd0b84 289#undef FUNC_NAME
0f2d19dd 290
c2da2648
GH
291/* move up to read_len chars from port's putback and/or read buffers
292 into memory starting at dest. returns the number of chars moved. */
293size_t scm_take_from_input_buffers (SCM port, char *dest, size_t read_len)
294{
92c2555f 295 scm_t_port *pt = SCM_PTAB_ENTRY (port);
c2da2648
GH
296 size_t chars_read = 0;
297 size_t from_buf = min (pt->read_end - pt->read_pos, read_len);
298
299 if (from_buf > 0)
300 {
301 memcpy (dest, pt->read_pos, from_buf);
302 pt->read_pos += from_buf;
303 chars_read += from_buf;
304 read_len -= from_buf;
305 dest += from_buf;
306 }
307
308 /* if putback was active, try the real input buffer too. */
309 if (pt->read_buf == pt->putback_buf)
310 {
311 from_buf = min (pt->saved_read_end - pt->saved_read_pos, read_len);
312 if (from_buf > 0)
313 {
314 memcpy (dest, pt->saved_read_pos, from_buf);
315 pt->saved_read_pos += from_buf;
316 chars_read += from_buf;
317 }
318 }
319 return chars_read;
320}
321
6c951427 322/* Clear a port's read buffers, returning the contents. */
a1ec6916 323SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
1bbd0b84 324 (SCM port),
4a151b3d
GH
325 "This procedure clears a port's input buffers, similar\n"
326 "to the way that force-output clears the output buffer. The\n"
327 "contents of the buffers are returned as a single string, e.g.,\n"
328 "\n"
329 "@lisp\n"
330 "(define p (open-input-file ...))\n"
331 "(drain-input p) => empty string, nothing buffered yet.\n"
332 "(unread-char (read-char p) p)\n"
333 "(drain-input p) => initial chars from p, up to the buffer size.\n"
334 "@end lisp\n\n"
335 "Draining the buffers may be useful for cleanly finishing\n"
336 "buffered I/O so that the file descriptor can be used directly\n"
337 "for further input.")
1bbd0b84 338#define FUNC_NAME s_scm_drain_input
ee149d03 339{
840ae05d 340 SCM result;
3a5fb14d 341 char *data;
28a6e1b0 342 scm_t_port *pt;
c014a02e 343 long count;
ee149d03 344
34d19ef6 345 SCM_VALIDATE_OPINPORT (1, port);
28a6e1b0 346 pt = SCM_PTAB_ENTRY (port);
840ae05d 347
6c951427
GH
348 count = pt->read_end - pt->read_pos;
349 if (pt->read_buf == pt->putback_buf)
350 count += pt->saved_read_end - pt->saved_read_pos;
840ae05d 351
3a5fb14d
MV
352 result = scm_i_make_string (count, &data);
353 scm_take_from_input_buffers (port, data, count);
840ae05d 354 return result;
ee149d03 355}
1bbd0b84 356#undef FUNC_NAME
0f2d19dd
JB
357
358\f
d68fee48 359/* Standard ports --- current input, output, error, and more(!). */
0f2d19dd 360
9de87eea
MV
361static SCM cur_inport_fluid;
362static SCM cur_outport_fluid;
363static SCM cur_errport_fluid;
364static SCM cur_loadport_fluid;
365
3b3b36dd 366SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
e1546b65
MG
367 (),
368 "Return the current input port. This is the default port used\n"
369 "by many input procedures. Initially, @code{current-input-port}\n"
370 "returns the @dfn{standard input} in Unix and C terminology.")
1bbd0b84 371#define FUNC_NAME s_scm_current_input_port
0f2d19dd 372{
9de87eea 373 return scm_fluid_ref (cur_inport_fluid);
0f2d19dd 374}
1bbd0b84 375#undef FUNC_NAME
0f2d19dd 376
3b3b36dd 377SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
e1546b65
MG
378 (),
379 "Return the current output port. This is the default port used\n"
9401323e 380 "by many output procedures. Initially,\n"
e1546b65
MG
381 "@code{current-output-port} returns the @dfn{standard output} in\n"
382 "Unix and C terminology.")
1bbd0b84 383#define FUNC_NAME s_scm_current_output_port
0f2d19dd 384{
9de87eea 385 return scm_fluid_ref (cur_outport_fluid);
0f2d19dd 386}
1bbd0b84 387#undef FUNC_NAME
0f2d19dd 388
3b3b36dd 389SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
1bbd0b84 390 (),
b380b885
MD
391 "Return the port to which errors and warnings should be sent (the\n"
392 "@dfn{standard error} in Unix and C terminology).")
1bbd0b84 393#define FUNC_NAME s_scm_current_error_port
0f2d19dd 394{
9de87eea 395 return scm_fluid_ref (cur_errport_fluid);
0f2d19dd 396}
1bbd0b84 397#undef FUNC_NAME
0f2d19dd 398
3b3b36dd 399SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
e1546b65 400 (),
b450f070 401 "Return the current-load-port.\n"
e1546b65 402 "The load port is used internally by @code{primitive-load}.")
1bbd0b84 403#define FUNC_NAME s_scm_current_load_port
31614d8e 404{
9de87eea 405 return scm_fluid_ref (cur_loadport_fluid);
31614d8e 406}
1bbd0b84 407#undef FUNC_NAME
31614d8e 408
3b3b36dd 409SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
1bbd0b84 410 (SCM port),
8f85c0c6
NJ
411 "@deffnx {Scheme Procedure} set-current-output-port port\n"
412 "@deffnx {Scheme Procedure} set-current-error-port port\n"
b380b885
MD
413 "Change the ports returned by @code{current-input-port},\n"
414 "@code{current-output-port} and @code{current-error-port}, respectively,\n"
415 "so that they use the supplied @var{port} for input or output.")
1bbd0b84 416#define FUNC_NAME s_scm_set_current_input_port
0f2d19dd 417{
9de87eea 418 SCM oinp = scm_fluid_ref (cur_inport_fluid);
34d19ef6 419 SCM_VALIDATE_OPINPORT (1, port);
9de87eea 420 scm_fluid_set_x (cur_inport_fluid, port);
0f2d19dd
JB
421 return oinp;
422}
1bbd0b84 423#undef FUNC_NAME
0f2d19dd
JB
424
425
3b3b36dd 426SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
e1546b65
MG
427 (SCM port),
428 "Set the current default output port to @var{port}.")
1bbd0b84 429#define FUNC_NAME s_scm_set_current_output_port
0f2d19dd 430{
9de87eea 431 SCM ooutp = scm_fluid_ref (cur_outport_fluid);
78446828 432 port = SCM_COERCE_OUTPORT (port);
34d19ef6 433 SCM_VALIDATE_OPOUTPORT (1, port);
9de87eea 434 scm_fluid_set_x (cur_outport_fluid, port);
0f2d19dd
JB
435 return ooutp;
436}
1bbd0b84 437#undef FUNC_NAME
0f2d19dd
JB
438
439
3b3b36dd 440SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
e1546b65
MG
441 (SCM port),
442 "Set the current default error port to @var{port}.")
1bbd0b84 443#define FUNC_NAME s_scm_set_current_error_port
0f2d19dd 444{
9de87eea 445 SCM oerrp = scm_fluid_ref (cur_errport_fluid);
78446828 446 port = SCM_COERCE_OUTPORT (port);
34d19ef6 447 SCM_VALIDATE_OPOUTPORT (1, port);
9de87eea 448 scm_fluid_set_x (cur_errport_fluid, port);
0f2d19dd
JB
449 return oerrp;
450}
1bbd0b84 451#undef FUNC_NAME
0f2d19dd 452
185e369a 453void
661ae7ab 454scm_dynwind_current_input_port (SCM port)
9de87eea 455#define FUNC_NAME NULL
185e369a 456{
9de87eea 457 SCM_VALIDATE_OPINPORT (1, port);
661ae7ab 458 scm_dynwind_fluid (cur_inport_fluid, port);
185e369a 459}
9de87eea 460#undef FUNC_NAME
185e369a
MV
461
462void
661ae7ab 463scm_dynwind_current_output_port (SCM port)
9de87eea 464#define FUNC_NAME NULL
185e369a 465{
9de87eea
MV
466 port = SCM_COERCE_OUTPORT (port);
467 SCM_VALIDATE_OPOUTPORT (1, port);
661ae7ab 468 scm_dynwind_fluid (cur_outport_fluid, port);
185e369a 469}
9de87eea 470#undef FUNC_NAME
185e369a
MV
471
472void
661ae7ab 473scm_dynwind_current_error_port (SCM port)
9de87eea
MV
474#define FUNC_NAME NULL
475{
476 port = SCM_COERCE_OUTPORT (port);
477 SCM_VALIDATE_OPOUTPORT (1, port);
661ae7ab 478 scm_dynwind_fluid (cur_errport_fluid, port);
9de87eea
MV
479}
480#undef FUNC_NAME
481
482void
661ae7ab 483scm_i_dynwind_current_load_port (SCM port)
185e369a 484{
661ae7ab 485 scm_dynwind_fluid (cur_loadport_fluid, port);
185e369a
MV
486}
487
0f2d19dd 488\f
840ae05d 489/* The port table --- an array of pointers to ports. */
0f2d19dd 490
5dbc6c06
HWN
491/*
492 We need a global registry of ports to flush them all at exit, and to
493 get all the ports matching a file descriptor.
494 */
495SCM scm_i_port_weak_hash;
0f2d19dd 496
9de87eea 497scm_i_pthread_mutex_t scm_i_port_table_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
b9ad392e
MD
498
499/* This function is not and should not be thread safe. */
1cc91f1b 500
da220f27
HWN
501SCM
502scm_new_port_table_entry (scm_t_bits tag)
402788a9 503#define FUNC_NAME "scm_new_port_table_entry"
0f2d19dd 504{
85835e59
HWN
505 /*
506 We initialize the cell to empty, this is in case scm_gc_calloc
507 triggers GC ; we don't want the GC to scan a half-finished Z.
508 */
509
67329a9e 510 SCM z = scm_cons (SCM_EOL, SCM_EOL);
39e8f371 511 scm_t_port *entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
5f16b897 512
840ae05d 513 entry->file_name = SCM_BOOL_F;
61e452ba 514 entry->rw_active = SCM_PORT_NEITHER;
5dbc6c06 515 entry->port = z;
5f16b897 516
5dbc6c06
HWN
517 SCM_SET_CELL_TYPE (z, tag);
518 SCM_SETPTAB_ENTRY (z, entry);
519
520 scm_hashq_set_x (scm_i_port_weak_hash, z, SCM_BOOL_F);
840ae05d 521
da220f27 522 return z;
0f2d19dd 523}
c6c79933 524#undef FUNC_NAME
0f2d19dd 525
67329a9e
HWN
526#if SCM_ENABLE_DEPRECATED==1
527SCM_API scm_t_port *
528scm_add_to_port_table (SCM port)
529{
530 SCM z = scm_new_port_table_entry (scm_tc7_port);
531 scm_t_port * pt = SCM_PTAB_ENTRY(z);
532
533 pt->port = port;
5dbc6c06
HWN
534 SCM_SETCAR (z, SCM_EOL);
535 SCM_SETCDR (z, SCM_EOL);
85835e59 536 SCM_SETPTAB_ENTRY (port, pt);
67329a9e
HWN
537 return pt;
538}
539#endif
540
541
6c951427 542/* Remove a port from the table and destroy it. */
b9ad392e
MD
543
544/* This function is not and should not be thread safe. */
0f2d19dd 545void
5dbc6c06
HWN
546scm_i_remove_port (SCM port)
547#define FUNC_NAME "scm_remove_port"
0f2d19dd 548{
92c2555f 549 scm_t_port *p = SCM_PTAB_ENTRY (port);
6c951427 550 if (p->putback_buf)
4c9419ac
MV
551 scm_gc_free (p->putback_buf, p->putback_buf_size, "putback buffer");
552 scm_gc_free (p, sizeof (scm_t_port), "port");
5dbc6c06 553
0f2d19dd 554 SCM_SETPTAB_ENTRY (port, 0);
5dbc6c06 555 scm_hashq_remove_x (scm_i_port_weak_hash, port);
0f2d19dd 556}
db4b4ca6
DH
557#undef FUNC_NAME
558
0f2d19dd 559
b450f070 560/* Functions for debugging. */
5dbc6c06 561#ifdef GUILE_DEBUG
3b3b36dd 562SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
b450f070 563 (),
1e6808ea 564 "Return the number of ports in the port table. @code{pt-size}\n"
5352393c 565 "is only included in @code{--enable-guile-debug} builds.")
1bbd0b84 566#define FUNC_NAME s_scm_pt_size
0f2d19dd 567{
5dbc6c06 568 return scm_from_int (SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash));
0f2d19dd 569}
1bbd0b84 570#undef FUNC_NAME
0f2d19dd
JB
571#endif
572
70df8af6 573void
92c2555f 574scm_port_non_buffer (scm_t_port *pt)
70df8af6
GH
575{
576 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
577 pt->write_buf = pt->write_pos = &pt->shortbuf;
578 pt->read_buf_size = pt->write_buf_size = 1;
579 pt->write_end = pt->write_buf + pt->write_buf_size;
580}
0f2d19dd 581
d68fee48
JB
582\f
583/* Revealed counts --- an oddity inherited from SCSH. */
584
8b13c6b3
GH
585/* Find a port in the table and return its revealed count.
586 Also used by the garbage collector.
0f2d19dd 587 */
1cc91f1b 588
0f2d19dd 589int
a284e297 590scm_revealed_count (SCM port)
0f2d19dd
JB
591{
592 return SCM_REVEALED(port);
593}
594
595
596
597/* Return the revealed count for a port. */
598
3b3b36dd 599SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
1bbd0b84 600 (SCM port),
1e6808ea 601 "Return the revealed count for @var{port}.")
1bbd0b84 602#define FUNC_NAME s_scm_port_revealed
0f2d19dd 603{
78446828 604 port = SCM_COERCE_OUTPORT (port);
34d19ef6 605 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 606 return scm_from_int (scm_revealed_count (port));
0f2d19dd 607}
1bbd0b84 608#undef FUNC_NAME
0f2d19dd
JB
609
610/* Set the revealed count for a port. */
3b3b36dd 611SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
1bbd0b84 612 (SCM port, SCM rcount),
b450f070 613 "Sets the revealed count for a port to a given value.\n"
b380b885 614 "The return value is unspecified.")
1bbd0b84 615#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 616{
78446828 617 port = SCM_COERCE_OUTPORT (port);
34d19ef6 618 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 619 SCM_REVEALED (port) = scm_to_int (rcount);
8b13c6b3 620 return SCM_UNSPECIFIED;
0f2d19dd 621}
1bbd0b84 622#undef FUNC_NAME
0f2d19dd 623
d68fee48
JB
624
625\f
626/* Retrieving a port's mode. */
627
eadd48de
GH
628/* Return the flags that characterize a port based on the mode
629 * string used to open a file for that port.
630 *
631 * See PORT FLAGS in scm.h
632 */
633
3a5fb14d
MV
634static long
635scm_i_mode_bits_n (const char *modes, size_t n)
636{
637 return (SCM_OPN
638 | (memchr (modes, 'r', n) || memchr (modes, '+', n) ? SCM_RDNG : 0)
639 | ( memchr (modes, 'w', n)
640 || memchr (modes, 'a', n)
641 || memchr (modes, '+', n) ? SCM_WRTNG : 0)
642 | (memchr (modes, '0', n) ? SCM_BUF0 : 0)
643 | (memchr (modes, 'l', n) ? SCM_BUFLINE : 0));
644}
645
eadd48de 646long
a284e297 647scm_mode_bits (char *modes)
eadd48de 648{
3a5fb14d 649 return scm_i_mode_bits_n (modes, strlen (modes));
eadd48de
GH
650}
651
d617ee18
MV
652long
653scm_i_mode_bits (SCM modes)
654{
655 long bits;
656
657 if (!scm_is_string (modes))
658 scm_wrong_type_arg_msg (NULL, 0, modes, "string");
659
3a5fb14d
MV
660 bits = scm_i_mode_bits_n (scm_i_string_chars (modes),
661 scm_i_string_length (modes));
d617ee18
MV
662 scm_remember_upto_here_1 (modes);
663 return bits;
664}
eadd48de
GH
665
666/* Return the mode flags from an open port.
667 * Some modes such as "append" are only used when opening
668 * a file and are not returned here. */
669
3b3b36dd 670SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
1bbd0b84 671 (SCM port),
1e6808ea
MG
672 "Return the port modes associated with the open port @var{port}.\n"
673 "These will not necessarily be identical to the modes used when\n"
674 "the port was opened, since modes such as \"append\" which are\n"
675 "used only during port creation are not retained.")
1bbd0b84 676#define FUNC_NAME s_scm_port_mode
eadd48de 677{
26a3038d 678 char modes[4];
eadd48de 679 modes[0] = '\0';
78446828
MV
680
681 port = SCM_COERCE_OUTPORT (port);
34d19ef6 682 SCM_VALIDATE_OPPORT (1, port);
f9a64404
DH
683 if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
684 if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de
GH
685 strcpy (modes, "r+");
686 else
687 strcpy (modes, "r");
688 }
f9a64404 689 else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de 690 strcpy (modes, "w");
f9a64404 691 if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
eadd48de 692 strcat (modes, "0");
3a5fb14d 693 return scm_from_locale_string (modes);
eadd48de 694}
1bbd0b84 695#undef FUNC_NAME
eadd48de
GH
696
697
d68fee48
JB
698\f
699/* Closing ports. */
700
0f2d19dd
JB
701/* scm_close_port
702 * Call the close operation on a port object.
eadd48de 703 * see also scm_close.
0f2d19dd 704 */
3b3b36dd 705SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
1bbd0b84 706 (SCM port),
1e6808ea
MG
707 "Close the specified port object. Return @code{#t} if it\n"
708 "successfully closes a port or @code{#f} if it was already\n"
709 "closed. An exception may be raised if an error occurs, for\n"
710 "example when flushing buffered output. See also @ref{Ports and\n"
711 "File Descriptors, close}, for a procedure which can close file\n"
712 "descriptors.")
1bbd0b84 713#define FUNC_NAME s_scm_close_port
0f2d19dd 714{
1be6b49c 715 size_t i;
eadd48de
GH
716 int rv;
717
78446828
MV
718 port = SCM_COERCE_OUTPORT (port);
719
7a754ca6 720 SCM_VALIDATE_PORT (1, port);
0f2d19dd 721 if (SCM_CLOSEDP (port))
eadd48de 722 return SCM_BOOL_F;
0f2d19dd 723 i = SCM_PTOBNUM (port);
affc96b5
GH
724 if (scm_ptobs[i].close)
725 rv = (scm_ptobs[i].close) (port);
eadd48de
GH
726 else
727 rv = 0;
9de87eea 728 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
5dbc6c06 729 scm_i_remove_port (port);
9de87eea 730 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
22a52da1 731 SCM_CLR_PORT_OPEN_FLAG (port);
7888309b 732 return scm_from_bool (rv >= 0);
7a754ca6
MD
733}
734#undef FUNC_NAME
735
736SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
737 (SCM port),
738 "Close the specified input port object. The routine has no effect if\n"
739 "the file has already been closed. An exception may be raised if an\n"
740 "error occurs. The value returned is unspecified.\n\n"
741 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
742 "which can close file descriptors.")
743#define FUNC_NAME s_scm_close_input_port
744{
745 SCM_VALIDATE_INPUT_PORT (1, port);
746 scm_close_port (port);
747 return SCM_UNSPECIFIED;
748}
749#undef FUNC_NAME
750
751SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
752 (SCM port),
753 "Close the specified output port object. The routine has no effect if\n"
754 "the file has already been closed. An exception may be raised if an\n"
755 "error occurs. The value returned is unspecified.\n\n"
756 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
757 "which can close file descriptors.")
758#define FUNC_NAME s_scm_close_output_port
759{
760 port = SCM_COERCE_OUTPORT (port);
761 SCM_VALIDATE_OUTPUT_PORT (1, port);
762 scm_close_port (port);
763 return SCM_UNSPECIFIED;
0f2d19dd 764}
1bbd0b84 765#undef FUNC_NAME
0f2d19dd 766
5dbc6c06
HWN
767static SCM
768scm_i_collect_keys_in_vector (void *closure, SCM key, SCM value, SCM result)
769{
770 int *i = (int*) closure;
771 scm_c_vector_set_x (result, *i, key);
772 (*i)++;
773
774 return result;
775}
776
c536b4b3
MV
777void
778scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
c2ca4493 779{
5dbc6c06 780 int i = 0;
3a5fb14d 781 size_t n;
fdfe6305
MV
782 SCM ports;
783
fdfe6305
MV
784 /* Even without pre-emptive multithreading, running arbitrary code
785 while scanning the port table is unsafe because the port table
3a5fb14d
MV
786 can change arbitrarily (from a GC, for example). So we first
787 collect the ports into a vector. -mvo */
fdfe6305 788
9de87eea 789 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
5dbc6c06 790 n = SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash);
9de87eea 791 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
4057a3e0 792 ports = scm_c_make_vector (n, SCM_BOOL_F);
3a5fb14d 793
5dbc6c06
HWN
794 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
795 ports = scm_internal_hash_fold (scm_i_collect_keys_in_vector, &i,
796 ports, scm_i_port_weak_hash);
9de87eea 797 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
3a5fb14d 798
5dbc6c06
HWN
799 for (i = 0; i < n; i++) {
800 SCM p = SCM_SIMPLE_VECTOR_REF (ports, i);
801 if (SCM_PORTP (p))
802 proc (data, p);
803 }
bd83658e
RB
804
805 scm_remember_upto_here_1 (ports);
c536b4b3 806}
fdfe6305 807
c536b4b3
MV
808SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
809 (SCM proc),
810 "Apply @var{proc} to each port in the Guile port table\n"
811 "in turn. The return value is unspecified. More specifically,\n"
812 "@var{proc} is applied exactly once to every port that exists\n"
813 "in the system at the time @var{port-for-each} is invoked.\n"
814 "Changes to the port table while @var{port-for-each} is running\n"
815 "have no effect as far as @var{port-for-each} is concerned.")
816#define FUNC_NAME s_scm_port_for_each
817{
818 SCM_VALIDATE_PROC (1, proc);
819
820 scm_c_port_for_each ((void (*)(void*,SCM))scm_call_1, proc);
c2ca4493
GH
821 return SCM_UNSPECIFIED;
822}
823#undef FUNC_NAME
824
c536b4b3 825
d68fee48
JB
826\f
827/* Utter miscellany. Gosh, we should clean this up some time. */
828
3b3b36dd 829SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
1bbd0b84 830 (SCM x),
1e6808ea
MG
831 "Return @code{#t} if @var{x} is an input port, otherwise return\n"
832 "@code{#f}. Any object satisfying this predicate also satisfies\n"
833 "@code{port?}.")
1bbd0b84 834#define FUNC_NAME s_scm_input_port_p
0f2d19dd 835{
7888309b 836 return scm_from_bool (SCM_INPUT_PORT_P (x));
0f2d19dd 837}
1bbd0b84 838#undef FUNC_NAME
0f2d19dd 839
3b3b36dd 840SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
1bbd0b84 841 (SCM x),
1e6808ea
MG
842 "Return @code{#t} if @var{x} is an output port, otherwise return\n"
843 "@code{#f}. Any object satisfying this predicate also satisfies\n"
844 "@code{port?}.")
1bbd0b84 845#define FUNC_NAME s_scm_output_port_p
0f2d19dd 846{
82893676 847 x = SCM_COERCE_OUTPORT (x);
7888309b 848 return scm_from_bool (SCM_OUTPUT_PORT_P (x));
0f2d19dd 849}
1bbd0b84 850#undef FUNC_NAME
0f2d19dd 851
eb5c0a2a
GH
852SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
853 (SCM x),
1e6808ea 854 "Return a boolean indicating whether @var{x} is a port.\n"
5352393c
MG
855 "Equivalent to @code{(or (input-port? @var{x}) (output-port?\n"
856 "@var{x}))}.")
eb5c0a2a
GH
857#define FUNC_NAME s_scm_port_p
858{
7888309b 859 return scm_from_bool (SCM_PORTP (x));
eb5c0a2a
GH
860}
861#undef FUNC_NAME
862
3b3b36dd 863SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
1bbd0b84 864 (SCM port),
1e6808ea
MG
865 "Return @code{#t} if @var{port} is closed or @code{#f} if it is\n"
866 "open.")
1bbd0b84 867#define FUNC_NAME s_scm_port_closed_p
60d0643d 868{
34d19ef6 869 SCM_VALIDATE_PORT (1, port);
7888309b 870 return scm_from_bool (!SCM_OPPORTP (port));
60d0643d 871}
1bbd0b84 872#undef FUNC_NAME
0f2d19dd 873
3b3b36dd 874SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
1bbd0b84 875 (SCM x),
1e6808ea
MG
876 "Return @code{#t} if @var{x} is an end-of-file object; otherwise\n"
877 "return @code{#f}.")
1bbd0b84 878#define FUNC_NAME s_scm_eof_object_p
0f2d19dd 879{
7888309b 880 return scm_from_bool(SCM_EOF_OBJECT_P (x));
0f2d19dd 881}
1bbd0b84 882#undef FUNC_NAME
0f2d19dd 883
3b3b36dd 884SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
1bbd0b84 885 (SCM port),
b380b885 886 "Flush the specified output port, or the current output port if @var{port}\n"
9401323e 887 "is omitted. The current output buffer contents are passed to the\n"
b380b885
MD
888 "underlying port implementation (e.g., in the case of fports, the\n"
889 "data will be written to the file and the output buffer will be cleared.)\n"
890 "It has no effect on an unbuffered port.\n\n"
891 "The return value is unspecified.")
1bbd0b84 892#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
893{
894 if (SCM_UNBNDP (port))
9de87eea 895 port = scm_current_output_port ();
0f2d19dd 896 else
78446828
MV
897 {
898 port = SCM_COERCE_OUTPORT (port);
34d19ef6 899 SCM_VALIDATE_OPOUTPORT (1, port);
78446828 900 }
affc96b5 901 scm_flush (port);
ee149d03 902 return SCM_UNSPECIFIED;
0f2d19dd 903}
1bbd0b84 904#undef FUNC_NAME
0f2d19dd 905
5dbc6c06
HWN
906
907static void
61d3568b 908flush_output_port (void *closure, SCM port)
5dbc6c06 909{
5dbc6c06
HWN
910 if (SCM_OPOUTPORTP (port))
911 scm_flush (port);
912}
913
a1ec6916 914SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
1bbd0b84 915 (),
b380b885
MD
916 "Equivalent to calling @code{force-output} on\n"
917 "all open output ports. The return value is unspecified.")
1bbd0b84 918#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c 919{
5dbc6c06 920 scm_c_port_for_each (&flush_output_port, NULL);
89ea5b7c
GH
921 return SCM_UNSPECIFIED;
922}
1bbd0b84 923#undef FUNC_NAME
0f2d19dd 924
3b3b36dd 925SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1bbd0b84 926 (SCM port),
1e6808ea
MG
927 "Return the next character available from @var{port}, updating\n"
928 "@var{port} to point to the following character. If no more\n"
929 "characters are available, the end-of-file object is returned.")
1bbd0b84 930#define FUNC_NAME s_scm_read_char
0f2d19dd
JB
931{
932 int c;
933 if (SCM_UNBNDP (port))
9de87eea 934 port = scm_current_input_port ();
34d19ef6 935 SCM_VALIDATE_OPINPORT (1, port);
b7f3516f 936 c = scm_getc (port);
0f2d19dd
JB
937 if (EOF == c)
938 return SCM_EOF_VAL;
7866a09b 939 return SCM_MAKE_CHAR (c);
0f2d19dd 940}
1bbd0b84 941#undef FUNC_NAME
0f2d19dd 942
5c070ca7 943/* this should only be called when the read buffer is empty. it
affc96b5 944 tries to refill the read buffer. it returns the first char from
5c070ca7 945 the port, which is either EOF or *(pt->read_pos). */
6c951427 946int
affc96b5 947scm_fill_input (SCM port)
6c951427 948{
92c2555f 949 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e 950
b5cb4464
NJ
951 assert (pt->read_pos == pt->read_end);
952
6c951427
GH
953 if (pt->read_buf == pt->putback_buf)
954 {
955 /* finished reading put-back chars. */
956 pt->read_buf = pt->saved_read_buf;
957 pt->read_pos = pt->saved_read_pos;
958 pt->read_end = pt->saved_read_end;
959 pt->read_buf_size = pt->saved_read_buf_size;
960 if (pt->read_pos < pt->read_end)
5c070ca7 961 return *(pt->read_pos);
6c951427 962 }
affc96b5 963 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
964}
965
3cb988bd 966
6fe692e9
MD
967/* scm_lfwrite
968 *
53802ea8
MV
969 * This function differs from scm_c_write; it updates port line and
970 * column. */
6fe692e9 971
ee149d03 972void
1be6b49c 973scm_lfwrite (const char *ptr, size_t size, SCM port)
ee149d03 974{
92c2555f
MV
975 scm_t_port *pt = SCM_PTAB_ENTRY (port);
976 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 977
840ae05d 978 if (pt->rw_active == SCM_PORT_READ)
affc96b5 979 scm_end_input (port);
283a1a0e 980
31703ab8 981 ptob->write (port, ptr, size);
840ae05d 982
53802ea8 983 for (; size; ptr++, size--) {
a727f4f6
KR
984 if (*ptr == '\a') {
985 }
986 else if (*ptr == '\b') {
987 SCM_DECCOL(port);
988 }
989 else if (*ptr == '\n') {
53802ea8
MV
990 SCM_INCLINE(port);
991 }
a727f4f6
KR
992 else if (*ptr == '\r') {
993 SCM_ZEROCOL(port);
994 }
53802ea8
MV
995 else if (*ptr == '\t') {
996 SCM_TABCOL(port);
997 }
998 else {
999 SCM_INCCOL(port);
1000 }
1001 }
1002
840ae05d
JB
1003 if (pt->rw_random)
1004 pt->rw_active = SCM_PORT_WRITE;
ee149d03 1005}
3cb988bd 1006
6fe692e9
MD
1007/* scm_c_read
1008 *
1009 * Used by an application to read arbitrary number of bytes from an
1010 * SCM port. Same semantics as libc read, except that scm_c_read only
1011 * returns less than SIZE bytes if at end-of-file.
1012 *
1013 * Warning: Doesn't update port line and column counts! */
1014
b5cb4464
NJ
1015/* This structure, and the following swap_buffer function, are used
1016 for temporarily swapping a port's own read buffer, and the buffer
1017 that the caller of scm_c_read provides. */
1018struct port_and_swap_buffer
1019{
1020 scm_t_port *pt;
1021 unsigned char *buffer;
1022 size_t size;
1023};
1024
1025static void
1026swap_buffer (void *data)
1027{
1028 struct port_and_swap_buffer *psb = (struct port_and_swap_buffer *) data;
1029 unsigned char *old_buf = psb->pt->read_buf;
1030 size_t old_size = psb->pt->read_buf_size;
1031
1032 /* Make the port use (buffer, size) from the struct. */
1033 psb->pt->read_pos = psb->pt->read_buf = psb->pt->read_end = psb->buffer;
1034 psb->pt->read_buf_size = psb->size;
1035
1036 /* Save the port's old (buffer, size) in the struct. */
1037 psb->buffer = old_buf;
1038 psb->size = old_size;
1039}
1040
1be6b49c
ML
1041size_t
1042scm_c_read (SCM port, void *buffer, size_t size)
693758d5 1043#define FUNC_NAME "scm_c_read"
6fe692e9 1044{
693758d5 1045 scm_t_port *pt;
1be6b49c 1046 size_t n_read = 0, n_available;
b5cb4464 1047 struct port_and_swap_buffer psb;
6fe692e9 1048
693758d5
LC
1049 SCM_VALIDATE_OPINPORT (1, port);
1050
1051 pt = SCM_PTAB_ENTRY (port);
6fe692e9
MD
1052 if (pt->rw_active == SCM_PORT_WRITE)
1053 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
1054
1055 if (pt->rw_random)
1056 pt->rw_active = SCM_PORT_READ;
1057
b5cb4464
NJ
1058 /* Take bytes first from the port's read buffer. */
1059 if (pt->read_pos < pt->read_end)
6fe692e9 1060 {
b5cb4464 1061 n_available = min (size, pt->read_end - pt->read_pos);
6fe692e9 1062 memcpy (buffer, pt->read_pos, n_available);
910d1e40 1063 buffer = (char *) buffer + n_available;
6fe692e9
MD
1064 pt->read_pos += n_available;
1065 n_read += n_available;
6fe692e9 1066 size -= n_available;
6fe692e9
MD
1067 }
1068
b5cb4464
NJ
1069 /* Avoid the scm_dynwind_* costs if we now have enough data. */
1070 if (size == 0)
1071 return n_read;
1072
1073 /* Now we will call scm_fill_input repeatedly until we have read the
1074 requested number of bytes. (Note that a single scm_fill_input
1075 call does not guarantee to fill the whole of the port's read
6d227556
NJ
1076 buffer.) */
1077 if (pt->read_buf_size <= 1)
b5cb4464 1078 {
6d227556
NJ
1079 /* The port that we are reading from is unbuffered - i.e. does
1080 not have its own persistent buffer - but we have a buffer,
1081 provided by our caller, that is the right size for the data
1082 that is wanted. For the following scm_fill_input calls,
1083 therefore, we use the buffer in hand as the port's read
1084 buffer.
1085
1086 We need to make sure that the port's normal (1 byte) buffer
1087 is reinstated in case one of the scm_fill_input () calls
1088 throws an exception; we use the scm_dynwind_* API to achieve
1089 that. */
1090 psb.pt = pt;
1091 psb.buffer = buffer;
1092 psb.size = size;
1093 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1094 scm_dynwind_rewind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1095 scm_dynwind_unwind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1096
1097 /* Call scm_fill_input until we have all the bytes that we need,
1098 or we hit EOF. */
1099 while (pt->read_buf_size && (scm_fill_input (port) != EOF))
1100 {
1101 pt->read_buf_size -= (pt->read_end - pt->read_pos);
1102 pt->read_pos = pt->read_buf = pt->read_end;
1103 }
1104 n_read += pt->read_buf - (unsigned char *) buffer;
b5cb4464 1105
6d227556
NJ
1106 /* Reinstate the port's normal buffer. */
1107 scm_dynwind_end ();
1108 }
1109 else
1110 {
1111 /* The port has its own buffer. It is important that we use it,
1112 even if it happens to be smaller than our caller's buffer, so
1113 that a custom port implementation's entry points (in
1114 particular, fill_input) can rely on the buffer always being
1115 the same as they first set up. */
1116 while (size && (scm_fill_input (port) != EOF))
1117 {
1118 n_available = min (size, pt->read_end - pt->read_pos);
1119 memcpy (buffer, pt->read_pos, n_available);
1120 buffer = (char *) buffer + n_available;
1121 pt->read_pos += n_available;
1122 n_read += n_available;
1123 size -= n_available;
1124 }
1125 }
6fe692e9 1126
b5cb4464 1127 return n_read;
6fe692e9 1128}
693758d5 1129#undef FUNC_NAME
6fe692e9
MD
1130
1131/* scm_c_write
1132 *
1133 * Used by an application to write arbitrary number of bytes to an SCM
1134 * port. Similar semantics as libc write. However, unlike libc
1135 * write, scm_c_write writes the requested number of bytes and has no
1136 * return value.
1137 *
1138 * Warning: Doesn't update port line and column counts!
1139 */
1140
693758d5 1141void
1be6b49c 1142scm_c_write (SCM port, const void *ptr, size_t size)
693758d5 1143#define FUNC_NAME "scm_c_write"
6fe692e9 1144{
693758d5
LC
1145 scm_t_port *pt;
1146 scm_t_ptob_descriptor *ptob;
1147
1148 SCM_VALIDATE_OPOUTPORT (1, port);
1149
1150 pt = SCM_PTAB_ENTRY (port);
1151 ptob = &scm_ptobs[SCM_PTOBNUM (port)];
6fe692e9
MD
1152
1153 if (pt->rw_active == SCM_PORT_READ)
1154 scm_end_input (port);
1155
1156 ptob->write (port, ptr, size);
1157
1158 if (pt->rw_random)
1159 pt->rw_active = SCM_PORT_WRITE;
1160}
693758d5 1161#undef FUNC_NAME
3cb988bd 1162
ee149d03 1163void
a284e297 1164scm_flush (SCM port)
ee149d03 1165{
c014a02e 1166 long i = SCM_PTOBNUM (port);
affc96b5 1167 (scm_ptobs[i].flush) (port);
ee149d03
JB
1168}
1169
283a1a0e 1170void
a284e297 1171scm_end_input (SCM port)
283a1a0e 1172{
c014a02e 1173 long offset;
92c2555f 1174 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e
GH
1175
1176 if (pt->read_buf == pt->putback_buf)
1177 {
1178 offset = pt->read_end - pt->read_pos;
1179 pt->read_buf = pt->saved_read_buf;
1180 pt->read_pos = pt->saved_read_pos;
1181 pt->read_end = pt->saved_read_end;
1182 pt->read_buf_size = pt->saved_read_buf_size;
1183 }
1184 else
1185 offset = 0;
1186
affc96b5 1187 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
1188}
1189
ee149d03
JB
1190\f
1191
1192
1193void
a284e297 1194scm_ungetc (int c, SCM port)
c6c79933 1195#define FUNC_NAME "scm_ungetc"
ee149d03 1196{
92c2555f 1197 scm_t_port *pt = SCM_PTAB_ENTRY (port);
840ae05d 1198
6c951427
GH
1199 if (pt->read_buf == pt->putback_buf)
1200 /* already using the put-back buffer. */
1201 {
1202 /* enlarge putback_buf if necessary. */
1203 if (pt->read_end == pt->read_buf + pt->read_buf_size
1204 && pt->read_buf == pt->read_pos)
1205 {
1be6b49c 1206 size_t new_size = pt->read_buf_size * 2;
c6c79933 1207 unsigned char *tmp = (unsigned char *)
4c9419ac
MV
1208 scm_gc_realloc (pt->putback_buf, pt->read_buf_size, new_size,
1209 "putback buffer");
6c951427 1210
6c951427
GH
1211 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
1212 pt->read_end = pt->read_buf + pt->read_buf_size;
1213 pt->read_buf_size = pt->putback_buf_size = new_size;
1214 }
1215
1216 /* shift any existing bytes to buffer + 1. */
1217 if (pt->read_pos == pt->read_end)
1218 pt->read_end = pt->read_buf + 1;
1219 else if (pt->read_pos != pt->read_buf + 1)
1220 {
1221 int count = pt->read_end - pt->read_pos;
1222
1223 memmove (pt->read_buf + 1, pt->read_pos, count);
1224 pt->read_end = pt->read_buf + 1 + count;
1225 }
1226
1227 pt->read_pos = pt->read_buf;
1228 }
1229 else
1230 /* switch to the put-back buffer. */
1231 {
1232 if (pt->putback_buf == NULL)
1233 {
c357d546 1234 pt->putback_buf
4c9419ac
MV
1235 = (unsigned char *) scm_gc_malloc (SCM_INITIAL_PUTBACK_BUF_SIZE,
1236 "putback buffer");
6c951427
GH
1237 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
1238 }
1239
1240 pt->saved_read_buf = pt->read_buf;
1241 pt->saved_read_pos = pt->read_pos;
1242 pt->saved_read_end = pt->read_end;
1243 pt->saved_read_buf_size = pt->read_buf_size;
1244
1245 pt->read_pos = pt->read_buf = pt->putback_buf;
1246 pt->read_end = pt->read_buf + 1;
1247 pt->read_buf_size = pt->putback_buf_size;
1248 }
1249
1250 *pt->read_buf = c;
ee149d03 1251
840ae05d
JB
1252 if (pt->rw_random)
1253 pt->rw_active = SCM_PORT_READ;
1254
ee149d03
JB
1255 if (c == '\n')
1256 {
1257 /* What should col be in this case?
1258 * We'll leave it at -1.
1259 */
1260 SCM_LINUM (port) -= 1;
1261 }
1262 else
1263 SCM_COL(port) -= 1;
1264}
c6c79933 1265#undef FUNC_NAME
ee149d03
JB
1266
1267
1268void
70d63753 1269scm_ungets (const char *s, int n, SCM port)
ee149d03
JB
1270{
1271 /* This is simple minded and inefficient, but unreading strings is
1272 * probably not a common operation, and remember that line and
1273 * column numbers have to be handled...
1274 *
1275 * Please feel free to write an optimized version!
1276 */
1277 while (n--)
1278 scm_ungetc (s[n], port);
1279}
1280
1281
3b3b36dd 1282SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1bbd0b84 1283 (SCM port),
1e6808ea
MG
1284 "Return the next character available from @var{port},\n"
1285 "@emph{without} updating @var{port} to point to the following\n"
1286 "character. If no more characters are available, the\n"
c2dfff19
KR
1287 "end-of-file object is returned.\n"
1288 "\n"
1289 "The value returned by\n"
1e6808ea
MG
1290 "a call to @code{peek-char} is the same as the value that would\n"
1291 "have been returned by a call to @code{read-char} on the same\n"
1292 "port. The only difference is that the very next call to\n"
1293 "@code{read-char} or @code{peek-char} on that @var{port} will\n"
1294 "return the value returned by the preceding call to\n"
1295 "@code{peek-char}. In particular, a call to @code{peek-char} on\n"
1296 "an interactive port will hang waiting for input whenever a call\n"
c2dfff19 1297 "to @code{read-char} would have hung.")
1bbd0b84 1298#define FUNC_NAME s_scm_peek_char
ee149d03 1299{
1a973c42 1300 int c, column;
ee149d03 1301 if (SCM_UNBNDP (port))
9de87eea 1302 port = scm_current_input_port ();
ee149d03 1303 else
34d19ef6 1304 SCM_VALIDATE_OPINPORT (1, port);
1a973c42 1305 column = SCM_COL(port);
ee149d03
JB
1306 c = scm_getc (port);
1307 if (EOF == c)
1308 return SCM_EOF_VAL;
1309 scm_ungetc (c, port);
1a973c42 1310 SCM_COL(port) = column;
7866a09b 1311 return SCM_MAKE_CHAR (c);
3cb988bd 1312}
1bbd0b84 1313#undef FUNC_NAME
3cb988bd 1314
1be4270a 1315SCM_DEFINE (scm_unread_char, "unread-char", 1, 1, 0,
1bbd0b84 1316 (SCM cobj, SCM port),
b380b885
MD
1317 "Place @var{char} in @var{port} so that it will be read by the\n"
1318 "next read operation. If called multiple times, the unread characters\n"
1319 "will be read again in last-in first-out order. If @var{port} is\n"
1320 "not supplied, the current input port is used.")
1bbd0b84 1321#define FUNC_NAME s_scm_unread_char
0f2d19dd
JB
1322{
1323 int c;
1324
34d19ef6 1325 SCM_VALIDATE_CHAR (1, cobj);
0f2d19dd 1326 if (SCM_UNBNDP (port))
9de87eea 1327 port = scm_current_input_port ();
0f2d19dd 1328 else
34d19ef6 1329 SCM_VALIDATE_OPINPORT (2, port);
0f2d19dd 1330
7866a09b 1331 c = SCM_CHAR (cobj);
0f2d19dd 1332
b7f3516f 1333 scm_ungetc (c, port);
0f2d19dd
JB
1334 return cobj;
1335}
1bbd0b84 1336#undef FUNC_NAME
0f2d19dd 1337
a1ec6916 1338SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1bbd0b84 1339 (SCM str, SCM port),
b380b885
MD
1340 "Place the string @var{str} in @var{port} so that its characters will be\n"
1341 "read in subsequent read operations. If called multiple times, the\n"
1342 "unread characters will be read again in last-in first-out order. If\n"
1343 "@var{port} is not supplied, the current-input-port is used.")
1bbd0b84 1344#define FUNC_NAME s_scm_unread_string
ee1e7e13 1345{
34d19ef6 1346 SCM_VALIDATE_STRING (1, str);
ee1e7e13 1347 if (SCM_UNBNDP (port))
9de87eea 1348 port = scm_current_input_port ();
ee1e7e13 1349 else
34d19ef6 1350 SCM_VALIDATE_OPINPORT (2, port);
ee1e7e13 1351
3a5fb14d 1352 scm_ungets (scm_i_string_chars (str), scm_i_string_length (str), port);
ee1e7e13
MD
1353
1354 return str;
1355}
1bbd0b84 1356#undef FUNC_NAME
ee1e7e13 1357
a1ec6916 1358SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1e6808ea
MG
1359 (SCM fd_port, SCM offset, SCM whence),
1360 "Sets the current position of @var{fd/port} to the integer\n"
1361 "@var{offset}, which is interpreted according to the value of\n"
1362 "@var{whence}.\n"
1363 "\n"
1364 "One of the following variables should be supplied for\n"
1365 "@var{whence}:\n"
b380b885
MD
1366 "@defvar SEEK_SET\n"
1367 "Seek from the beginning of the file.\n"
1368 "@end defvar\n"
1369 "@defvar SEEK_CUR\n"
1370 "Seek from the current position.\n"
1371 "@end defvar\n"
1372 "@defvar SEEK_END\n"
1373 "Seek from the end of the file.\n"
1e6808ea
MG
1374 "@end defvar\n"
1375 "If @var{fd/port} is a file descriptor, the underlying system\n"
1376 "call is @code{lseek}. @var{port} may be a string port.\n"
1377 "\n"
1378 "The value returned is the new position in the file. This means\n"
1379 "that the current position of a port can be obtained using:\n"
1380 "@lisp\n"
b380b885 1381 "(seek port 0 SEEK_CUR)\n"
1e6808ea 1382 "@end lisp")
1bbd0b84 1383#define FUNC_NAME s_scm_seek
840ae05d 1384{
840ae05d
JB
1385 int how;
1386
1e6808ea 1387 fd_port = SCM_COERCE_OUTPORT (fd_port);
840ae05d 1388
a55c2b68 1389 how = scm_to_int (whence);
840ae05d 1390 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1bbd0b84 1391 SCM_OUT_OF_RANGE (3, whence);
23f2b9a3 1392
8ab3d8a0
KR
1393 if (SCM_OPFPORTP (fd_port))
1394 {
1395 /* go direct to fport code to allow 64-bit offsets */
1396 return scm_i_fport_seek (fd_port, offset, how);
1397 }
1398 else if (SCM_OPPORTP (fd_port))
840ae05d 1399 {
92c2555f 1400 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (fd_port);
23f2b9a3
KR
1401 off_t off = scm_to_off_t (offset);
1402 off_t rv;
840ae05d
JB
1403
1404 if (!ptob->seek)
1bbd0b84 1405 SCM_MISC_ERROR ("port is not seekable",
1e6808ea 1406 scm_cons (fd_port, SCM_EOL));
840ae05d 1407 else
1e6808ea 1408 rv = ptob->seek (fd_port, off, how);
23f2b9a3 1409 return scm_from_off_t (rv);
840ae05d
JB
1410 }
1411 else /* file descriptor?. */
1412 {
23f2b9a3
KR
1413 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1414 off_t_or_off64_t rv;
1415 rv = lseek_or_lseek64 (scm_to_int (fd_port), off, how);
840ae05d 1416 if (rv == -1)
1bbd0b84 1417 SCM_SYSERROR;
23f2b9a3 1418 return scm_from_off_t_or_off64_t (rv);
840ae05d 1419 }
840ae05d 1420}
1bbd0b84 1421#undef FUNC_NAME
840ae05d 1422
8ab3d8a0
KR
1423#ifndef O_BINARY
1424#define O_BINARY 0
1425#endif
1426
1427/* Mingw has ftruncate(), perhaps implemented above using chsize, but
1428 doesn't have the filename version truncate(), hence this code. */
1429#if HAVE_FTRUNCATE && ! HAVE_TRUNCATE
1430static int
1431truncate (const char *file, off_t length)
82893676 1432{
8ab3d8a0
KR
1433 int ret, fdes;
1434
1435 fdes = open (file, O_BINARY | O_WRONLY);
1436 if (fdes == -1)
1437 return -1;
1438
1439 ret = ftruncate (fdes, length);
1440 if (ret == -1)
82893676 1441 {
8ab3d8a0 1442 int save_errno = errno;
82893676 1443 close (fdes);
8ab3d8a0
KR
1444 errno = save_errno;
1445 return -1;
82893676 1446 }
8ab3d8a0
KR
1447
1448 return close (fdes);
82893676 1449}
8ab3d8a0 1450#endif /* HAVE_FTRUNCATE && ! HAVE_TRUNCATE */
82893676 1451
a1ec6916 1452SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1bbd0b84 1453 (SCM object, SCM length),
8ab3d8a0
KR
1454 "Truncate @var{file} to @var{length} bytes. @var{file} can be a\n"
1455 "filename string, a port object, or an integer file descriptor.\n"
1456 "The return value is unspecified.\n"
1457 "\n"
1458 "For a port or file descriptor @var{length} can be omitted, in\n"
1459 "which case the file is truncated at the current position (per\n"
1460 "@code{ftell} above).\n"
1461 "\n"
1462 "On most systems a file can be extended by giving a length\n"
1463 "greater than the current size, but this is not mandatory in the\n"
1464 "POSIX standard.")
1bbd0b84 1465#define FUNC_NAME s_scm_truncate_file
840ae05d 1466{
69bc9ff3 1467 int rv;
69bc9ff3 1468
2b829bbb
KR
1469 /* "object" can be a port, fdes or filename.
1470
1471 Negative "length" makes no sense, but it's left to truncate() or
1472 ftruncate() to give back an error for that (normally EINVAL).
1473 */
840ae05d 1474
840ae05d
JB
1475 if (SCM_UNBNDP (length))
1476 {
69bc9ff3 1477 /* must supply length if object is a filename. */
7f9994d9 1478 if (scm_is_string (object))
34d19ef6 1479 SCM_MISC_ERROR("must supply length if OBJECT is a filename", SCM_EOL);
69bc9ff3 1480
e11e83f3 1481 length = scm_seek (object, SCM_INUM0, scm_from_int (SEEK_CUR));
840ae05d 1482 }
3fe6190f 1483
69bc9ff3 1484 object = SCM_COERCE_OUTPORT (object);
e11e83f3 1485 if (scm_is_integer (object))
69bc9ff3 1486 {
23f2b9a3
KR
1487 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
1488 SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
1489 c_length));
69bc9ff3 1490 }
8ab3d8a0
KR
1491 else if (SCM_OPOUTFPORTP (object))
1492 {
1493 /* go direct to fport code to allow 64-bit offsets */
1494 rv = scm_i_fport_truncate (object, length);
1495 }
0c95b57d 1496 else if (SCM_OPOUTPORTP (object))
69bc9ff3 1497 {
2b829bbb 1498 off_t c_length = scm_to_off_t (length);
92c2555f
MV
1499 scm_t_port *pt = SCM_PTAB_ENTRY (object);
1500 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1501
affc96b5 1502 if (!ptob->truncate)
1bbd0b84 1503 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1504 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1505 scm_end_input (object);
69bc9ff3 1506 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1507 ptob->flush (object);
69bc9ff3 1508
affc96b5 1509 ptob->truncate (object, c_length);
69bc9ff3
GH
1510 rv = 0;
1511 }
1512 else
1513 {
2b829bbb 1514 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
7f9994d9
MV
1515 char *str = scm_to_locale_string (object);
1516 int eno;
2b829bbb 1517 SCM_SYSCALL (rv = truncate_or_truncate64 (str, c_length));
7f9994d9
MV
1518 eno = errno;
1519 free (str);
1520 errno = eno;
69bc9ff3
GH
1521 }
1522 if (rv == -1)
1bbd0b84 1523 SCM_SYSERROR;
840ae05d
JB
1524 return SCM_UNSPECIFIED;
1525}
1bbd0b84 1526#undef FUNC_NAME
840ae05d 1527
a1ec6916 1528SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1bbd0b84 1529 (SCM port),
a150979d
KR
1530 "Return the current line number for @var{port}.\n"
1531 "\n"
1532 "The first line of a file is 0. But you might want to add 1\n"
1533 "when printing line numbers, since starting from 1 is\n"
1534 "traditional in error messages, and likely to be more natural to\n"
1535 "non-programmers.")
1bbd0b84 1536#define FUNC_NAME s_scm_port_line
0f2d19dd 1537{
78446828 1538 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1539 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1540 return scm_from_long (SCM_LINUM (port));
0f2d19dd 1541}
1bbd0b84 1542#undef FUNC_NAME
0f2d19dd 1543
a1ec6916 1544SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1bbd0b84 1545 (SCM port, SCM line),
a150979d
KR
1546 "Set the current line number for @var{port} to @var{line}. The\n"
1547 "first line of a file is 0.")
1bbd0b84 1548#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1549{
360fc44c 1550 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1551 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1552 SCM_PTAB_ENTRY (port)->line_number = scm_to_long (line);
564478fd 1553 return SCM_UNSPECIFIED;
d043d8c2 1554}
1bbd0b84 1555#undef FUNC_NAME
d043d8c2 1556
a1ec6916 1557SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1bbd0b84 1558 (SCM port),
a150979d
KR
1559 "Return the current column number of @var{port}.\n"
1560 "If the number is\n"
b380b885
MD
1561 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1562 "- i.e. the first character of the first line is line 0, column 0.\n"
1563 "(However, when you display a file position, for example in an error\n"
650a1cf9 1564 "message, we recommend you add 1 to get 1-origin integers. This is\n"
b380b885
MD
1565 "because lines and column numbers traditionally start with 1, and that is\n"
1566 "what non-programmers will find most natural.)")
1bbd0b84 1567#define FUNC_NAME s_scm_port_column
0f2d19dd 1568{
78446828 1569 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1570 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 1571 return scm_from_int (SCM_COL (port));
0f2d19dd 1572}
1bbd0b84 1573#undef FUNC_NAME
0f2d19dd 1574
a1ec6916 1575SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1bbd0b84 1576 (SCM port, SCM column),
a150979d
KR
1577 "Set the current column of @var{port}. Before reading the first\n"
1578 "character on a line the column should be 0.")
1bbd0b84 1579#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1580{
360fc44c 1581 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1582 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 1583 SCM_PTAB_ENTRY (port)->column_number = scm_to_int (column);
564478fd 1584 return SCM_UNSPECIFIED;
d043d8c2 1585}
1bbd0b84 1586#undef FUNC_NAME
d043d8c2 1587
a1ec6916 1588SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1bbd0b84 1589 (SCM port),
b380b885 1590 "Return the filename associated with @var{port}. This function returns\n"
2a2a730b 1591 "the strings \"standard input\", \"standard output\" and \"standard error\"\n"
a3c8b9fc 1592 "when called on the current input, output and error ports respectively.")
1bbd0b84 1593#define FUNC_NAME s_scm_port_filename
0f2d19dd 1594{
78446828 1595 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1596 SCM_VALIDATE_OPENPORT (1, port);
b24b5e13 1597 return SCM_FILENAME (port);
0f2d19dd 1598}
1bbd0b84 1599#undef FUNC_NAME
0f2d19dd 1600
a1ec6916 1601SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1bbd0b84 1602 (SCM port, SCM filename),
b380b885
MD
1603 "Change the filename associated with @var{port}, using the current input\n"
1604 "port if none is specified. Note that this does not change the port's\n"
1605 "source of data, but only the value that is returned by\n"
1606 "@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1607#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1608{
360fc44c 1609 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1610 SCM_VALIDATE_OPENPORT (1, port);
360fc44c 1611 /* We allow the user to set the filename to whatever he likes. */
b24b5e13
DH
1612 SCM_SET_FILENAME (port, filename);
1613 return SCM_UNSPECIFIED;
d14af9f2 1614}
1bbd0b84 1615#undef FUNC_NAME
d14af9f2 1616
f12733c9
MD
1617void
1618scm_print_port_mode (SCM exp, SCM port)
1619{
1620 scm_puts (SCM_CLOSEDP (exp)
1621 ? "closed: "
f9a64404
DH
1622 : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
1623 ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1624 ? "input-output: "
1625 : "input: ")
f9a64404 1626 : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1627 ? "output: "
1628 : "bogus: ")),
1629 port);
1630}
1cc91f1b 1631
f12733c9 1632int
e81d98ec 1633scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 1634{
f12733c9
MD
1635 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1636 if (!type)
1637 type = "port";
b7f3516f 1638 scm_puts ("#<", port);
f12733c9 1639 scm_print_port_mode (exp, port);
b7f3516f
TT
1640 scm_puts (type, port);
1641 scm_putc (' ', port);
0345e278 1642 scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
b7f3516f 1643 scm_putc ('>', port);
f12733c9 1644 return 1;
0f2d19dd
JB
1645}
1646
0f2d19dd
JB
1647void
1648scm_ports_prehistory ()
0f2d19dd
JB
1649{
1650 scm_numptob = 0;
67329a9e 1651 scm_ptobs = (scm_t_ptob_descriptor *) scm_malloc (sizeof (scm_t_ptob_descriptor));
0f2d19dd 1652}
0f2d19dd
JB
1653
1654\f
ee149d03 1655
d68fee48 1656/* Void ports. */
0f2d19dd 1657
92c2555f 1658scm_t_bits scm_tc16_void_port = 0;
0f2d19dd 1659
e81d98ec 1660static int fill_input_void_port (SCM port SCM_UNUSED)
283a1a0e 1661{
70df8af6 1662 return EOF;
283a1a0e
GH
1663}
1664
31703ab8 1665static void
e81d98ec
DH
1666write_void_port (SCM port SCM_UNUSED,
1667 const void *data SCM_UNUSED,
1668 size_t size SCM_UNUSED)
31703ab8
GH
1669{
1670}
1671
d617ee18
MV
1672static SCM
1673scm_i_void_port (long mode_bits)
0f2d19dd 1674{
9de87eea 1675 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
402788a9 1676 {
da220f27
HWN
1677 SCM answer = scm_new_port_table_entry (scm_tc16_void_port);
1678 scm_t_port * pt = SCM_PTAB_ENTRY(answer);
1679
402788a9 1680 scm_port_non_buffer (pt);
402788a9
HWN
1681
1682 SCM_SETSTREAM (answer, 0);
1683 SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
9de87eea 1684 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
402788a9
HWN
1685 return answer;
1686 }
0f2d19dd
JB
1687}
1688
d617ee18
MV
1689SCM
1690scm_void_port (char *mode_str)
1691{
1692 return scm_i_void_port (scm_mode_bits (mode_str));
1693}
1694
a1ec6916 1695SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 1696 (SCM mode),
70df8af6 1697 "Create and return a new void port. A void port acts like\n"
bb2c02f2 1698 "@file{/dev/null}. The @var{mode} argument\n"
70df8af6 1699 "specifies the input/output modes for this port: see the\n"
b380b885 1700 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1701#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1702{
d617ee18 1703 return scm_i_void_port (scm_i_mode_bits (mode));
0f2d19dd 1704}
1bbd0b84 1705#undef FUNC_NAME
0f2d19dd 1706
0f2d19dd 1707\f
89545eba 1708/* Initialization. */
1cc91f1b 1709
0f2d19dd
JB
1710void
1711scm_init_ports ()
0f2d19dd 1712{
840ae05d 1713 /* lseek() symbols. */
e11e83f3
MV
1714 scm_c_define ("SEEK_SET", scm_from_int (SEEK_SET));
1715 scm_c_define ("SEEK_CUR", scm_from_int (SEEK_CUR));
1716 scm_c_define ("SEEK_END", scm_from_int (SEEK_END));
840ae05d 1717
70df8af6
GH
1718 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
1719 write_void_port);
9de87eea
MV
1720
1721 cur_inport_fluid = scm_permanent_object (scm_make_fluid ());
1722 cur_outport_fluid = scm_permanent_object (scm_make_fluid ());
1723 cur_errport_fluid = scm_permanent_object (scm_make_fluid ());
1724 cur_loadport_fluid = scm_permanent_object (scm_make_fluid ());
1725
5dbc6c06
HWN
1726 scm_i_port_weak_hash = scm_permanent_object (scm_make_weak_key_hash_table (SCM_I_MAKINUM(31)));
1727
a0599745 1728#include "libguile/ports.x"
0f2d19dd 1729}
89e00824
ML
1730
1731/*
1732 Local Variables:
1733 c-file-style: "gnu"
1734 End:
1735*/