Don't doubly define scm_t_wchar
[bpt/guile.git] / libguile / ports.c
CommitLineData
5bb2d903 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008, 2009 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>
e6e2e95a 33
a0599745 34#include "libguile/_scm.h"
4e047c3e 35#include "libguile/async.h"
f0942910 36#include "libguile/eval.h"
8ab3d8a0 37#include "libguile/fports.h" /* direct access for seek and truncate */
a0599745 38#include "libguile/objects.h"
9511876f 39#include "libguile/goops.h"
a0599745
MD
40#include "libguile/smob.h"
41#include "libguile/chars.h"
185e369a 42#include "libguile/dynwind.h"
0f2d19dd 43
a0599745 44#include "libguile/keywords.h"
5dbc6c06 45#include "libguile/hashtab.h"
a0599745
MD
46#include "libguile/root.h"
47#include "libguile/strings.h"
b42170a4 48#include "libguile/mallocs.h"
a0599745
MD
49#include "libguile/validate.h"
50#include "libguile/ports.h"
3a5fb14d 51#include "libguile/vectors.h"
5dbc6c06 52#include "libguile/weaks.h"
9de87eea 53#include "libguile/fluids.h"
0f2d19dd 54
bd9e24b3
GH
55#ifdef HAVE_STRING_H
56#include <string.h>
57#endif
58
0f2d19dd 59#ifdef HAVE_MALLOC_H
95b88819 60#include <malloc.h>
0f2d19dd
JB
61#endif
62
ec65f5da
MV
63#ifdef HAVE_IO_H
64#include <io.h>
65#endif
66
0f2d19dd
JB
67#ifdef HAVE_UNISTD_H
68#include <unistd.h>
69#endif
70
95b88819
GH
71#ifdef HAVE_SYS_IOCTL_H
72#include <sys/ioctl.h>
73#endif
d68fee48 74
8ab3d8a0
KR
75/* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize
76 already, but have this code here in case that wasn't so in past versions,
77 or perhaps to help other minimal DOS environments.
78
79 gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which
80 might be possibilities if we've got other systems without ftruncate. */
81
82#if HAVE_CHSIZE && ! HAVE_FTRUNCATE
82893676 83#define ftruncate(fd, size) chsize (fd, size)
8ab3d8a0
KR
84#undef HAVE_FTRUNCATE
85#define HAVE_FTRUNCATE 1
82893676
MG
86#endif
87
0f2d19dd 88\f
d68fee48 89/* The port kind table --- a dynamically resized array of port types. */
0f2d19dd
JB
90
91
92/* scm_ptobs scm_numptob
5dbc6c06 93 * implement a dynamically resized array of ptob records.
0f2d19dd
JB
94 * Indexes into this table are used when generating type
95 * tags for smobjects (if you know a tag you can get an index and conversely).
96 */
92c2555f 97scm_t_ptob_descriptor *scm_ptobs;
c014a02e 98long scm_numptob;
0f2d19dd 99
ee149d03 100/* GC marker for a port with stream of SCM type. */
0f2d19dd 101SCM
a284e297 102scm_markstream (SCM ptr)
0f2d19dd
JB
103{
104 int openp;
f9a64404 105 openp = SCM_CELL_WORD_0 (ptr) & SCM_OPN;
0f2d19dd 106 if (openp)
74a16888 107 return SCM_PACK (SCM_STREAM (ptr));
0f2d19dd
JB
108 else
109 return SCM_BOOL_F;
110}
111
f12733c9 112/*
f12733c9 113 * We choose to use an interface similar to the smob interface with
affc96b5 114 * fill_input and write as standard fields, passed to the port
f12733c9
MD
115 * type constructor, and optional fields set by setters.
116 */
117
70df8af6 118static void
e81d98ec 119flush_port_default (SCM port SCM_UNUSED)
70df8af6
GH
120{
121}
122
123static void
e81d98ec 124end_input_default (SCM port SCM_UNUSED, int offset SCM_UNUSED)
70df8af6
GH
125{
126}
0f2d19dd 127
4c9419ac
MV
128static size_t
129scm_port_free0 (SCM port)
130{
131 return 0;
132}
133
92c2555f 134scm_t_bits
f12733c9 135scm_make_port_type (char *name,
affc96b5 136 int (*fill_input) (SCM port),
8aa011a1 137 void (*write) (SCM port, const void *data, size_t size))
0f2d19dd
JB
138{
139 char *tmp;
5bb2d903 140 if (SCM_I_MAX_PORT_TYPE_COUNT - 1 <= scm_numptob)
0f2d19dd 141 goto ptoberr;
9de87eea 142 SCM_CRITICAL_SECTION_START;
f12733c9
MD
143 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
144 (1 + scm_numptob)
92c2555f 145 * sizeof (scm_t_ptob_descriptor)));
0f2d19dd
JB
146 if (tmp)
147 {
92c2555f 148 scm_ptobs = (scm_t_ptob_descriptor *) tmp;
affc96b5 149
f12733c9
MD
150 scm_ptobs[scm_numptob].name = name;
151 scm_ptobs[scm_numptob].mark = 0;
4c9419ac 152 scm_ptobs[scm_numptob].free = scm_port_free0;
f12733c9
MD
153 scm_ptobs[scm_numptob].print = scm_port_print;
154 scm_ptobs[scm_numptob].equalp = 0;
affc96b5
GH
155 scm_ptobs[scm_numptob].close = 0;
156
157 scm_ptobs[scm_numptob].write = write;
70df8af6 158 scm_ptobs[scm_numptob].flush = flush_port_default;
affc96b5 159
70df8af6 160 scm_ptobs[scm_numptob].end_input = end_input_default;
affc96b5
GH
161 scm_ptobs[scm_numptob].fill_input = fill_input;
162 scm_ptobs[scm_numptob].input_waiting = 0;
163
f12733c9 164 scm_ptobs[scm_numptob].seek = 0;
affc96b5
GH
165 scm_ptobs[scm_numptob].truncate = 0;
166
0f2d19dd
JB
167 scm_numptob++;
168 }
9de87eea 169 SCM_CRITICAL_SECTION_END;
0f2d19dd 170 if (!tmp)
2500356c
DH
171 {
172 ptoberr:
173 scm_memory_error ("scm_make_port_type");
174 }
f12733c9 175 /* Make a class object if Goops is present */
6290d3f1 176 if (SCM_UNPACK (scm_port_class[0]) != 0)
f12733c9 177 scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
0f2d19dd
JB
178 return scm_tc7_port + (scm_numptob - 1) * 256;
179}
180
f12733c9 181void
23f2b9a3 182scm_set_port_mark (scm_t_bits tc, SCM (*mark) (SCM))
f12733c9
MD
183{
184 scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
185}
186
187void
23f2b9a3 188scm_set_port_free (scm_t_bits tc, size_t (*free) (SCM))
f12733c9
MD
189{
190 scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
191}
192
193void
23f2b9a3 194scm_set_port_print (scm_t_bits tc, int (*print) (SCM exp, SCM port,
f12733c9
MD
195 scm_print_state *pstate))
196{
197 scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
198}
199
200void
23f2b9a3 201scm_set_port_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
f12733c9
MD
202{
203 scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
204}
205
31703ab8 206void
23f2b9a3 207scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port))
31703ab8 208{
affc96b5 209 scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
31703ab8
GH
210}
211
f12733c9 212void
23f2b9a3 213scm_set_port_end_input (scm_t_bits tc, void (*end_input) (SCM port, int offset))
f12733c9 214{
affc96b5 215 scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
f12733c9
MD
216}
217
218void
23f2b9a3 219scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
f12733c9 220{
affc96b5 221 scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
f12733c9
MD
222}
223
224void
f1ce9199
LC
225scm_set_port_seek (scm_t_bits tc,
226 scm_t_off (*seek) (SCM, scm_t_off, int))
f12733c9
MD
227{
228 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
229}
230
231void
f1ce9199 232scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM, scm_t_off))
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
0a94eb00 1393 if (SCM_OPPORTP (fd_port))
840ae05d 1394 {
92c2555f 1395 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (fd_port);
f1ce9199
LC
1396 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1397 off_t_or_off64_t rv;
840ae05d
JB
1398
1399 if (!ptob->seek)
1bbd0b84 1400 SCM_MISC_ERROR ("port is not seekable",
1e6808ea 1401 scm_cons (fd_port, SCM_EOL));
840ae05d 1402 else
1e6808ea 1403 rv = ptob->seek (fd_port, off, how);
f1ce9199 1404 return scm_from_off_t_or_off64_t (rv);
840ae05d
JB
1405 }
1406 else /* file descriptor?. */
1407 {
23f2b9a3
KR
1408 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1409 off_t_or_off64_t rv;
1410 rv = lseek_or_lseek64 (scm_to_int (fd_port), off, how);
840ae05d 1411 if (rv == -1)
1bbd0b84 1412 SCM_SYSERROR;
23f2b9a3 1413 return scm_from_off_t_or_off64_t (rv);
840ae05d 1414 }
840ae05d 1415}
1bbd0b84 1416#undef FUNC_NAME
840ae05d 1417
8ab3d8a0
KR
1418#ifndef O_BINARY
1419#define O_BINARY 0
1420#endif
1421
1422/* Mingw has ftruncate(), perhaps implemented above using chsize, but
1423 doesn't have the filename version truncate(), hence this code. */
1424#if HAVE_FTRUNCATE && ! HAVE_TRUNCATE
1425static int
1426truncate (const char *file, off_t length)
82893676 1427{
8ab3d8a0
KR
1428 int ret, fdes;
1429
1430 fdes = open (file, O_BINARY | O_WRONLY);
1431 if (fdes == -1)
1432 return -1;
1433
1434 ret = ftruncate (fdes, length);
1435 if (ret == -1)
82893676 1436 {
8ab3d8a0 1437 int save_errno = errno;
82893676 1438 close (fdes);
8ab3d8a0
KR
1439 errno = save_errno;
1440 return -1;
82893676 1441 }
8ab3d8a0
KR
1442
1443 return close (fdes);
82893676 1444}
8ab3d8a0 1445#endif /* HAVE_FTRUNCATE && ! HAVE_TRUNCATE */
82893676 1446
a1ec6916 1447SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1bbd0b84 1448 (SCM object, SCM length),
8ab3d8a0
KR
1449 "Truncate @var{file} to @var{length} bytes. @var{file} can be a\n"
1450 "filename string, a port object, or an integer file descriptor.\n"
1451 "The return value is unspecified.\n"
1452 "\n"
1453 "For a port or file descriptor @var{length} can be omitted, in\n"
1454 "which case the file is truncated at the current position (per\n"
1455 "@code{ftell} above).\n"
1456 "\n"
1457 "On most systems a file can be extended by giving a length\n"
1458 "greater than the current size, but this is not mandatory in the\n"
1459 "POSIX standard.")
1bbd0b84 1460#define FUNC_NAME s_scm_truncate_file
840ae05d 1461{
69bc9ff3 1462 int rv;
69bc9ff3 1463
2b829bbb
KR
1464 /* "object" can be a port, fdes or filename.
1465
1466 Negative "length" makes no sense, but it's left to truncate() or
1467 ftruncate() to give back an error for that (normally EINVAL).
1468 */
840ae05d 1469
840ae05d
JB
1470 if (SCM_UNBNDP (length))
1471 {
69bc9ff3 1472 /* must supply length if object is a filename. */
7f9994d9 1473 if (scm_is_string (object))
34d19ef6 1474 SCM_MISC_ERROR("must supply length if OBJECT is a filename", SCM_EOL);
69bc9ff3 1475
e11e83f3 1476 length = scm_seek (object, SCM_INUM0, scm_from_int (SEEK_CUR));
840ae05d 1477 }
3fe6190f 1478
69bc9ff3 1479 object = SCM_COERCE_OUTPORT (object);
e11e83f3 1480 if (scm_is_integer (object))
69bc9ff3 1481 {
23f2b9a3
KR
1482 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
1483 SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
1484 c_length));
69bc9ff3 1485 }
0c95b57d 1486 else if (SCM_OPOUTPORTP (object))
69bc9ff3 1487 {
f1ce9199 1488 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
92c2555f
MV
1489 scm_t_port *pt = SCM_PTAB_ENTRY (object);
1490 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1491
affc96b5 1492 if (!ptob->truncate)
1bbd0b84 1493 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1494 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1495 scm_end_input (object);
69bc9ff3 1496 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1497 ptob->flush (object);
69bc9ff3 1498
affc96b5 1499 ptob->truncate (object, c_length);
69bc9ff3
GH
1500 rv = 0;
1501 }
1502 else
1503 {
2b829bbb 1504 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
7f9994d9
MV
1505 char *str = scm_to_locale_string (object);
1506 int eno;
2b829bbb 1507 SCM_SYSCALL (rv = truncate_or_truncate64 (str, c_length));
7f9994d9
MV
1508 eno = errno;
1509 free (str);
1510 errno = eno;
69bc9ff3
GH
1511 }
1512 if (rv == -1)
1bbd0b84 1513 SCM_SYSERROR;
840ae05d
JB
1514 return SCM_UNSPECIFIED;
1515}
1bbd0b84 1516#undef FUNC_NAME
840ae05d 1517
a1ec6916 1518SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1bbd0b84 1519 (SCM port),
a150979d
KR
1520 "Return the current line number for @var{port}.\n"
1521 "\n"
1522 "The first line of a file is 0. But you might want to add 1\n"
1523 "when printing line numbers, since starting from 1 is\n"
1524 "traditional in error messages, and likely to be more natural to\n"
1525 "non-programmers.")
1bbd0b84 1526#define FUNC_NAME s_scm_port_line
0f2d19dd 1527{
78446828 1528 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1529 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1530 return scm_from_long (SCM_LINUM (port));
0f2d19dd 1531}
1bbd0b84 1532#undef FUNC_NAME
0f2d19dd 1533
a1ec6916 1534SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1bbd0b84 1535 (SCM port, SCM line),
a150979d
KR
1536 "Set the current line number for @var{port} to @var{line}. The\n"
1537 "first line of a file is 0.")
1bbd0b84 1538#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1539{
360fc44c 1540 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1541 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1542 SCM_PTAB_ENTRY (port)->line_number = scm_to_long (line);
564478fd 1543 return SCM_UNSPECIFIED;
d043d8c2 1544}
1bbd0b84 1545#undef FUNC_NAME
d043d8c2 1546
a1ec6916 1547SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1bbd0b84 1548 (SCM port),
a150979d
KR
1549 "Return the current column number of @var{port}.\n"
1550 "If the number is\n"
b380b885
MD
1551 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1552 "- i.e. the first character of the first line is line 0, column 0.\n"
1553 "(However, when you display a file position, for example in an error\n"
650a1cf9 1554 "message, we recommend you add 1 to get 1-origin integers. This is\n"
b380b885
MD
1555 "because lines and column numbers traditionally start with 1, and that is\n"
1556 "what non-programmers will find most natural.)")
1bbd0b84 1557#define FUNC_NAME s_scm_port_column
0f2d19dd 1558{
78446828 1559 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1560 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 1561 return scm_from_int (SCM_COL (port));
0f2d19dd 1562}
1bbd0b84 1563#undef FUNC_NAME
0f2d19dd 1564
a1ec6916 1565SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1bbd0b84 1566 (SCM port, SCM column),
a150979d
KR
1567 "Set the current column of @var{port}. Before reading the first\n"
1568 "character on a line the column should be 0.")
1bbd0b84 1569#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1570{
360fc44c 1571 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1572 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 1573 SCM_PTAB_ENTRY (port)->column_number = scm_to_int (column);
564478fd 1574 return SCM_UNSPECIFIED;
d043d8c2 1575}
1bbd0b84 1576#undef FUNC_NAME
d043d8c2 1577
a1ec6916 1578SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1bbd0b84 1579 (SCM port),
b380b885 1580 "Return the filename associated with @var{port}. This function returns\n"
2a2a730b 1581 "the strings \"standard input\", \"standard output\" and \"standard error\"\n"
a3c8b9fc 1582 "when called on the current input, output and error ports respectively.")
1bbd0b84 1583#define FUNC_NAME s_scm_port_filename
0f2d19dd 1584{
78446828 1585 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1586 SCM_VALIDATE_OPENPORT (1, port);
b24b5e13 1587 return SCM_FILENAME (port);
0f2d19dd 1588}
1bbd0b84 1589#undef FUNC_NAME
0f2d19dd 1590
a1ec6916 1591SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1bbd0b84 1592 (SCM port, SCM filename),
b380b885
MD
1593 "Change the filename associated with @var{port}, using the current input\n"
1594 "port if none is specified. Note that this does not change the port's\n"
1595 "source of data, but only the value that is returned by\n"
1596 "@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1597#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1598{
360fc44c 1599 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1600 SCM_VALIDATE_OPENPORT (1, port);
360fc44c 1601 /* We allow the user to set the filename to whatever he likes. */
b24b5e13
DH
1602 SCM_SET_FILENAME (port, filename);
1603 return SCM_UNSPECIFIED;
d14af9f2 1604}
1bbd0b84 1605#undef FUNC_NAME
d14af9f2 1606
f12733c9
MD
1607void
1608scm_print_port_mode (SCM exp, SCM port)
1609{
1610 scm_puts (SCM_CLOSEDP (exp)
1611 ? "closed: "
f9a64404
DH
1612 : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
1613 ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1614 ? "input-output: "
1615 : "input: ")
f9a64404 1616 : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1617 ? "output: "
1618 : "bogus: ")),
1619 port);
1620}
1cc91f1b 1621
f12733c9 1622int
e81d98ec 1623scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 1624{
f12733c9
MD
1625 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1626 if (!type)
1627 type = "port";
b7f3516f 1628 scm_puts ("#<", port);
f12733c9 1629 scm_print_port_mode (exp, port);
b7f3516f
TT
1630 scm_puts (type, port);
1631 scm_putc (' ', port);
0345e278 1632 scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
b7f3516f 1633 scm_putc ('>', port);
f12733c9 1634 return 1;
0f2d19dd
JB
1635}
1636
0f2d19dd
JB
1637void
1638scm_ports_prehistory ()
0f2d19dd
JB
1639{
1640 scm_numptob = 0;
67329a9e 1641 scm_ptobs = (scm_t_ptob_descriptor *) scm_malloc (sizeof (scm_t_ptob_descriptor));
0f2d19dd 1642}
0f2d19dd
JB
1643
1644\f
ee149d03 1645
d68fee48 1646/* Void ports. */
0f2d19dd 1647
92c2555f 1648scm_t_bits scm_tc16_void_port = 0;
0f2d19dd 1649
e81d98ec 1650static int fill_input_void_port (SCM port SCM_UNUSED)
283a1a0e 1651{
70df8af6 1652 return EOF;
283a1a0e
GH
1653}
1654
31703ab8 1655static void
e81d98ec
DH
1656write_void_port (SCM port SCM_UNUSED,
1657 const void *data SCM_UNUSED,
1658 size_t size SCM_UNUSED)
31703ab8
GH
1659{
1660}
1661
d617ee18
MV
1662static SCM
1663scm_i_void_port (long mode_bits)
0f2d19dd 1664{
9de87eea 1665 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
402788a9 1666 {
da220f27
HWN
1667 SCM answer = scm_new_port_table_entry (scm_tc16_void_port);
1668 scm_t_port * pt = SCM_PTAB_ENTRY(answer);
1669
402788a9 1670 scm_port_non_buffer (pt);
402788a9
HWN
1671
1672 SCM_SETSTREAM (answer, 0);
1673 SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
9de87eea 1674 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
402788a9
HWN
1675 return answer;
1676 }
0f2d19dd
JB
1677}
1678
d617ee18
MV
1679SCM
1680scm_void_port (char *mode_str)
1681{
1682 return scm_i_void_port (scm_mode_bits (mode_str));
1683}
1684
a1ec6916 1685SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 1686 (SCM mode),
70df8af6 1687 "Create and return a new void port. A void port acts like\n"
bb2c02f2 1688 "@file{/dev/null}. The @var{mode} argument\n"
70df8af6 1689 "specifies the input/output modes for this port: see the\n"
b380b885 1690 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1691#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1692{
d617ee18 1693 return scm_i_void_port (scm_i_mode_bits (mode));
0f2d19dd 1694}
1bbd0b84 1695#undef FUNC_NAME
0f2d19dd 1696
0f2d19dd 1697\f
89545eba 1698/* Initialization. */
1cc91f1b 1699
0f2d19dd
JB
1700void
1701scm_init_ports ()
0f2d19dd 1702{
840ae05d 1703 /* lseek() symbols. */
e11e83f3
MV
1704 scm_c_define ("SEEK_SET", scm_from_int (SEEK_SET));
1705 scm_c_define ("SEEK_CUR", scm_from_int (SEEK_CUR));
1706 scm_c_define ("SEEK_END", scm_from_int (SEEK_END));
840ae05d 1707
70df8af6
GH
1708 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
1709 write_void_port);
9de87eea
MV
1710
1711 cur_inport_fluid = scm_permanent_object (scm_make_fluid ());
1712 cur_outport_fluid = scm_permanent_object (scm_make_fluid ());
1713 cur_errport_fluid = scm_permanent_object (scm_make_fluid ());
1714 cur_loadport_fluid = scm_permanent_object (scm_make_fluid ());
1715
5dbc6c06
HWN
1716 scm_i_port_weak_hash = scm_permanent_object (scm_make_weak_key_hash_table (SCM_I_MAKINUM(31)));
1717
a0599745 1718#include "libguile/ports.x"
0f2d19dd 1719}
89e00824
ML
1720
1721/*
1722 Local Variables:
1723 c-file-style: "gnu"
1724 End:
1725*/