Merge branch 'master' into boehm-demers-weiser-gc
[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
fca43887
LC
33#include <assert.h>
34
a0599745 35#include "libguile/_scm.h"
4e047c3e 36#include "libguile/async.h"
f0942910 37#include "libguile/eval.h"
8ab3d8a0 38#include "libguile/fports.h" /* direct access for seek and truncate */
a0599745 39#include "libguile/objects.h"
9511876f 40#include "libguile/goops.h"
a0599745
MD
41#include "libguile/smob.h"
42#include "libguile/chars.h"
185e369a 43#include "libguile/dynwind.h"
0f2d19dd 44
a0599745 45#include "libguile/keywords.h"
5dbc6c06 46#include "libguile/hashtab.h"
a0599745
MD
47#include "libguile/root.h"
48#include "libguile/strings.h"
b42170a4 49#include "libguile/mallocs.h"
a0599745
MD
50#include "libguile/validate.h"
51#include "libguile/ports.h"
3a5fb14d 52#include "libguile/vectors.h"
5dbc6c06 53#include "libguile/weaks.h"
9de87eea 54#include "libguile/fluids.h"
0f2d19dd 55
bd9e24b3
GH
56#ifdef HAVE_STRING_H
57#include <string.h>
58#endif
59
ec65f5da
MV
60#ifdef HAVE_IO_H
61#include <io.h>
62#endif
63
0f2d19dd
JB
64#ifdef HAVE_UNISTD_H
65#include <unistd.h>
66#endif
67
95b88819
GH
68#ifdef HAVE_SYS_IOCTL_H
69#include <sys/ioctl.h>
70#endif
d68fee48 71
8ab3d8a0
KR
72/* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize
73 already, but have this code here in case that wasn't so in past versions,
74 or perhaps to help other minimal DOS environments.
75
76 gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which
77 might be possibilities if we've got other systems without ftruncate. */
78
79#if HAVE_CHSIZE && ! HAVE_FTRUNCATE
82893676 80#define ftruncate(fd, size) chsize (fd, size)
8ab3d8a0
KR
81#undef HAVE_FTRUNCATE
82#define HAVE_FTRUNCATE 1
82893676
MG
83#endif
84
0f2d19dd 85\f
d68fee48 86/* The port kind table --- a dynamically resized array of port types. */
0f2d19dd
JB
87
88
89/* scm_ptobs scm_numptob
5dbc6c06 90 * implement a dynamically resized array of ptob records.
0f2d19dd
JB
91 * Indexes into this table are used when generating type
92 * tags for smobjects (if you know a tag you can get an index and conversely).
93 */
92c2555f 94scm_t_ptob_descriptor *scm_ptobs;
c014a02e 95long scm_numptob;
0f2d19dd 96
ee149d03 97/* GC marker for a port with stream of SCM type. */
0f2d19dd 98SCM
a284e297 99scm_markstream (SCM ptr)
0f2d19dd
JB
100{
101 int openp;
f9a64404 102 openp = SCM_CELL_WORD_0 (ptr) & SCM_OPN;
0f2d19dd 103 if (openp)
74a16888 104 return SCM_PACK (SCM_STREAM (ptr));
0f2d19dd
JB
105 else
106 return SCM_BOOL_F;
107}
108
f12733c9 109/*
f12733c9 110 * We choose to use an interface similar to the smob interface with
affc96b5 111 * fill_input and write as standard fields, passed to the port
f12733c9
MD
112 * type constructor, and optional fields set by setters.
113 */
114
70df8af6 115static void
e81d98ec 116flush_port_default (SCM port SCM_UNUSED)
70df8af6
GH
117{
118}
119
120static void
e81d98ec 121end_input_default (SCM port SCM_UNUSED, int offset SCM_UNUSED)
70df8af6
GH
122{
123}
0f2d19dd 124
4c9419ac
MV
125static size_t
126scm_port_free0 (SCM port)
127{
128 return 0;
129}
130
92c2555f 131scm_t_bits
f12733c9 132scm_make_port_type (char *name,
affc96b5 133 int (*fill_input) (SCM port),
8aa011a1 134 void (*write) (SCM port, const void *data, size_t size))
0f2d19dd
JB
135{
136 char *tmp;
137 if (255 <= scm_numptob)
138 goto ptoberr;
9de87eea 139 SCM_CRITICAL_SECTION_START;
fca43887
LC
140 tmp = (char *) scm_gc_realloc ((char *) scm_ptobs,
141 scm_numptob * sizeof (scm_t_ptob_descriptor),
142 (1 + scm_numptob)
143 * sizeof (scm_t_ptob_descriptor),
144 "port-type");
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 498
651a0735
LC
499\f
500/* Port finalization. */
501
1cc91f1b 502
651a0735
LC
503static void finalize_port (GC_PTR, GC_PTR);
504
505/* Register a finalizer for PORT, if needed by its port type. */
506static SCM_C_INLINE_KEYWORD void
507register_finalizer_for_port (SCM port)
508{
509 long port_type;
510
511 port_type = SCM_TC2PTOBNUM (SCM_CELL_TYPE (port));
512 if (scm_ptobs[port_type].free)
513 {
514 GC_finalization_proc prev_finalizer;
515 GC_PTR prev_finalization_data;
516
517 GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (port), finalize_port, 0,
518 &prev_finalizer,
519 &prev_finalization_data);
520 }
521}
522
523/* Finalize the object (a port) pointed to by PTR. */
524static void
525finalize_port (GC_PTR ptr, GC_PTR data)
526{
527 long port_type;
528 SCM port = PTR2SCM (ptr);
529
530 if (!SCM_PORTP (port))
531 abort ();
532
533 if (SCM_OPENP (port))
534 {
535 if (SCM_REVEALED (port) > 0)
536 /* Keep "revealed" ports alive and re-register a finalizer. */
537 register_finalizer_for_port (port);
538 else
539 {
540 port_type = SCM_TC2PTOBNUM (SCM_CELL_TYPE (port));
541 if (port_type >= scm_numptob)
542 abort ();
543
544 if (scm_ptobs[port_type].free)
545 /* Yes, I really do mean `.free' rather than `.close'. `.close'
546 is for explicit `close-port' by user. */
547 scm_ptobs[port_type].free (port);
548
549 SCM_SETSTREAM (port, 0);
550 SCM_CLR_PORT_OPEN_FLAG (port);
651a0735
LC
551
552 scm_gc_ports_collected++;
553 }
554 }
555}
556
557
558
559\f
560
561/* This function is not and should not be thread safe. */
da220f27
HWN
562SCM
563scm_new_port_table_entry (scm_t_bits tag)
402788a9 564#define FUNC_NAME "scm_new_port_table_entry"
0f2d19dd 565{
85835e59
HWN
566 /*
567 We initialize the cell to empty, this is in case scm_gc_calloc
568 triggers GC ; we don't want the GC to scan a half-finished Z.
569 */
570
67329a9e 571 SCM z = scm_cons (SCM_EOL, SCM_EOL);
39e8f371 572 scm_t_port *entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
5f16b897 573
840ae05d 574 entry->file_name = SCM_BOOL_F;
61e452ba 575 entry->rw_active = SCM_PORT_NEITHER;
5dbc6c06 576 entry->port = z;
5f16b897 577
5dbc6c06
HWN
578 SCM_SET_CELL_TYPE (z, tag);
579 SCM_SETPTAB_ENTRY (z, entry);
840ae05d 580
5dbc6c06 581 scm_hashq_set_x (scm_i_port_weak_hash, z, SCM_BOOL_F);
651a0735
LC
582
583 /* For each new port, register a finalizer so that it port type's free
584 function can be invoked eventually. */
585 register_finalizer_for_port (z);
586
da220f27 587 return z;
0f2d19dd 588}
c6c79933 589#undef FUNC_NAME
0f2d19dd 590
67329a9e
HWN
591#if SCM_ENABLE_DEPRECATED==1
592SCM_API scm_t_port *
593scm_add_to_port_table (SCM port)
594{
595 SCM z = scm_new_port_table_entry (scm_tc7_port);
596 scm_t_port * pt = SCM_PTAB_ENTRY(z);
597
598 pt->port = port;
5dbc6c06
HWN
599 SCM_SETCAR (z, SCM_EOL);
600 SCM_SETCDR (z, SCM_EOL);
85835e59 601 SCM_SETPTAB_ENTRY (port, pt);
67329a9e
HWN
602 return pt;
603}
604#endif
605
606
6c951427 607/* Remove a port from the table and destroy it. */
b9ad392e
MD
608
609/* This function is not and should not be thread safe. */
0f2d19dd 610void
5dbc6c06
HWN
611scm_i_remove_port (SCM port)
612#define FUNC_NAME "scm_remove_port"
0f2d19dd 613{
92c2555f 614 scm_t_port *p = SCM_PTAB_ENTRY (port);
6c951427 615 if (p->putback_buf)
4c9419ac
MV
616 scm_gc_free (p->putback_buf, p->putback_buf_size, "putback buffer");
617 scm_gc_free (p, sizeof (scm_t_port), "port");
5dbc6c06 618
0f2d19dd 619 SCM_SETPTAB_ENTRY (port, 0);
5dbc6c06 620 scm_hashq_remove_x (scm_i_port_weak_hash, port);
0f2d19dd 621}
db4b4ca6
DH
622#undef FUNC_NAME
623
0f2d19dd 624
b450f070 625/* Functions for debugging. */
5dbc6c06 626#ifdef GUILE_DEBUG
3b3b36dd 627SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
b450f070 628 (),
1e6808ea 629 "Return the number of ports in the port table. @code{pt-size}\n"
5352393c 630 "is only included in @code{--enable-guile-debug} builds.")
1bbd0b84 631#define FUNC_NAME s_scm_pt_size
0f2d19dd 632{
5dbc6c06 633 return scm_from_int (SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash));
0f2d19dd 634}
1bbd0b84 635#undef FUNC_NAME
0f2d19dd
JB
636#endif
637
70df8af6 638void
92c2555f 639scm_port_non_buffer (scm_t_port *pt)
70df8af6
GH
640{
641 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
642 pt->write_buf = pt->write_pos = &pt->shortbuf;
643 pt->read_buf_size = pt->write_buf_size = 1;
644 pt->write_end = pt->write_buf + pt->write_buf_size;
645}
0f2d19dd 646
d68fee48
JB
647\f
648/* Revealed counts --- an oddity inherited from SCSH. */
649
8b13c6b3
GH
650/* Find a port in the table and return its revealed count.
651 Also used by the garbage collector.
0f2d19dd 652 */
1cc91f1b 653
0f2d19dd 654int
a284e297 655scm_revealed_count (SCM port)
0f2d19dd
JB
656{
657 return SCM_REVEALED(port);
658}
659
660
661
662/* Return the revealed count for a port. */
663
3b3b36dd 664SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
1bbd0b84 665 (SCM port),
1e6808ea 666 "Return the revealed count for @var{port}.")
1bbd0b84 667#define FUNC_NAME s_scm_port_revealed
0f2d19dd 668{
78446828 669 port = SCM_COERCE_OUTPORT (port);
34d19ef6 670 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 671 return scm_from_int (scm_revealed_count (port));
0f2d19dd 672}
1bbd0b84 673#undef FUNC_NAME
0f2d19dd
JB
674
675/* Set the revealed count for a port. */
3b3b36dd 676SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
1bbd0b84 677 (SCM port, SCM rcount),
b450f070 678 "Sets the revealed count for a port to a given value.\n"
b380b885 679 "The return value is unspecified.")
1bbd0b84 680#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 681{
78446828 682 port = SCM_COERCE_OUTPORT (port);
34d19ef6 683 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 684 SCM_REVEALED (port) = scm_to_int (rcount);
8b13c6b3 685 return SCM_UNSPECIFIED;
0f2d19dd 686}
1bbd0b84 687#undef FUNC_NAME
0f2d19dd 688
d68fee48
JB
689
690\f
691/* Retrieving a port's mode. */
692
eadd48de
GH
693/* Return the flags that characterize a port based on the mode
694 * string used to open a file for that port.
695 *
696 * See PORT FLAGS in scm.h
697 */
698
3a5fb14d
MV
699static long
700scm_i_mode_bits_n (const char *modes, size_t n)
701{
702 return (SCM_OPN
703 | (memchr (modes, 'r', n) || memchr (modes, '+', n) ? SCM_RDNG : 0)
704 | ( memchr (modes, 'w', n)
705 || memchr (modes, 'a', n)
706 || memchr (modes, '+', n) ? SCM_WRTNG : 0)
707 | (memchr (modes, '0', n) ? SCM_BUF0 : 0)
708 | (memchr (modes, 'l', n) ? SCM_BUFLINE : 0));
709}
710
eadd48de 711long
a284e297 712scm_mode_bits (char *modes)
eadd48de 713{
3a5fb14d 714 return scm_i_mode_bits_n (modes, strlen (modes));
eadd48de
GH
715}
716
d617ee18
MV
717long
718scm_i_mode_bits (SCM modes)
719{
720 long bits;
721
722 if (!scm_is_string (modes))
723 scm_wrong_type_arg_msg (NULL, 0, modes, "string");
724
3a5fb14d
MV
725 bits = scm_i_mode_bits_n (scm_i_string_chars (modes),
726 scm_i_string_length (modes));
d617ee18
MV
727 scm_remember_upto_here_1 (modes);
728 return bits;
729}
eadd48de
GH
730
731/* Return the mode flags from an open port.
732 * Some modes such as "append" are only used when opening
733 * a file and are not returned here. */
734
3b3b36dd 735SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
1bbd0b84 736 (SCM port),
1e6808ea
MG
737 "Return the port modes associated with the open port @var{port}.\n"
738 "These will not necessarily be identical to the modes used when\n"
739 "the port was opened, since modes such as \"append\" which are\n"
740 "used only during port creation are not retained.")
1bbd0b84 741#define FUNC_NAME s_scm_port_mode
eadd48de 742{
26a3038d 743 char modes[4];
eadd48de 744 modes[0] = '\0';
78446828
MV
745
746 port = SCM_COERCE_OUTPORT (port);
34d19ef6 747 SCM_VALIDATE_OPPORT (1, port);
f9a64404
DH
748 if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
749 if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de
GH
750 strcpy (modes, "r+");
751 else
752 strcpy (modes, "r");
753 }
f9a64404 754 else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de 755 strcpy (modes, "w");
f9a64404 756 if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
eadd48de 757 strcat (modes, "0");
3a5fb14d 758 return scm_from_locale_string (modes);
eadd48de 759}
1bbd0b84 760#undef FUNC_NAME
eadd48de
GH
761
762
d68fee48
JB
763\f
764/* Closing ports. */
765
0f2d19dd
JB
766/* scm_close_port
767 * Call the close operation on a port object.
eadd48de 768 * see also scm_close.
0f2d19dd 769 */
3b3b36dd 770SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
1bbd0b84 771 (SCM port),
1e6808ea
MG
772 "Close the specified port object. Return @code{#t} if it\n"
773 "successfully closes a port or @code{#f} if it was already\n"
774 "closed. An exception may be raised if an error occurs, for\n"
775 "example when flushing buffered output. See also @ref{Ports and\n"
776 "File Descriptors, close}, for a procedure which can close file\n"
777 "descriptors.")
1bbd0b84 778#define FUNC_NAME s_scm_close_port
0f2d19dd 779{
1be6b49c 780 size_t i;
eadd48de
GH
781 int rv;
782
78446828
MV
783 port = SCM_COERCE_OUTPORT (port);
784
7a754ca6 785 SCM_VALIDATE_PORT (1, port);
0f2d19dd 786 if (SCM_CLOSEDP (port))
eadd48de 787 return SCM_BOOL_F;
0f2d19dd 788 i = SCM_PTOBNUM (port);
affc96b5
GH
789 if (scm_ptobs[i].close)
790 rv = (scm_ptobs[i].close) (port);
eadd48de
GH
791 else
792 rv = 0;
9de87eea 793 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
5dbc6c06 794 scm_i_remove_port (port);
9de87eea 795 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
22a52da1 796 SCM_CLR_PORT_OPEN_FLAG (port);
7888309b 797 return scm_from_bool (rv >= 0);
7a754ca6
MD
798}
799#undef FUNC_NAME
800
801SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
802 (SCM port),
803 "Close the specified input port object. The routine has no effect if\n"
804 "the file has already been closed. An exception may be raised if an\n"
805 "error occurs. The value returned is unspecified.\n\n"
806 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
807 "which can close file descriptors.")
808#define FUNC_NAME s_scm_close_input_port
809{
810 SCM_VALIDATE_INPUT_PORT (1, port);
811 scm_close_port (port);
812 return SCM_UNSPECIFIED;
813}
814#undef FUNC_NAME
815
816SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
817 (SCM port),
818 "Close the specified output port object. The routine has no effect if\n"
819 "the file has already been closed. An exception may be raised if an\n"
820 "error occurs. The value returned is unspecified.\n\n"
821 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
822 "which can close file descriptors.")
823#define FUNC_NAME s_scm_close_output_port
824{
825 port = SCM_COERCE_OUTPORT (port);
826 SCM_VALIDATE_OUTPUT_PORT (1, port);
827 scm_close_port (port);
828 return SCM_UNSPECIFIED;
0f2d19dd 829}
1bbd0b84 830#undef FUNC_NAME
0f2d19dd 831
5dbc6c06
HWN
832static SCM
833scm_i_collect_keys_in_vector (void *closure, SCM key, SCM value, SCM result)
834{
835 int *i = (int*) closure;
836 scm_c_vector_set_x (result, *i, key);
837 (*i)++;
838
839 return result;
840}
841
c536b4b3
MV
842void
843scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
c2ca4493 844{
5dbc6c06 845 int i = 0;
3a5fb14d 846 size_t n;
fdfe6305
MV
847 SCM ports;
848
fdfe6305
MV
849 /* Even without pre-emptive multithreading, running arbitrary code
850 while scanning the port table is unsafe because the port table
3a5fb14d
MV
851 can change arbitrarily (from a GC, for example). So we first
852 collect the ports into a vector. -mvo */
fdfe6305 853
9de87eea 854 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
5dbc6c06 855 n = SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash);
9de87eea 856 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
4057a3e0 857 ports = scm_c_make_vector (n, SCM_BOOL_F);
3a5fb14d 858
5dbc6c06
HWN
859 scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
860 ports = scm_internal_hash_fold (scm_i_collect_keys_in_vector, &i,
861 ports, scm_i_port_weak_hash);
9de87eea 862 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
3a5fb14d 863
5dbc6c06
HWN
864 for (i = 0; i < n; i++) {
865 SCM p = SCM_SIMPLE_VECTOR_REF (ports, i);
866 if (SCM_PORTP (p))
867 proc (data, p);
868 }
bd83658e
RB
869
870 scm_remember_upto_here_1 (ports);
c536b4b3 871}
fdfe6305 872
c536b4b3
MV
873SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
874 (SCM proc),
875 "Apply @var{proc} to each port in the Guile port table\n"
876 "in turn. The return value is unspecified. More specifically,\n"
877 "@var{proc} is applied exactly once to every port that exists\n"
878 "in the system at the time @var{port-for-each} is invoked.\n"
879 "Changes to the port table while @var{port-for-each} is running\n"
880 "have no effect as far as @var{port-for-each} is concerned.")
881#define FUNC_NAME s_scm_port_for_each
882{
883 SCM_VALIDATE_PROC (1, proc);
884
885 scm_c_port_for_each ((void (*)(void*,SCM))scm_call_1, proc);
c2ca4493
GH
886 return SCM_UNSPECIFIED;
887}
888#undef FUNC_NAME
889
c536b4b3 890
d68fee48
JB
891\f
892/* Utter miscellany. Gosh, we should clean this up some time. */
893
3b3b36dd 894SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
1bbd0b84 895 (SCM x),
1e6808ea
MG
896 "Return @code{#t} if @var{x} is an input port, otherwise return\n"
897 "@code{#f}. Any object satisfying this predicate also satisfies\n"
898 "@code{port?}.")
1bbd0b84 899#define FUNC_NAME s_scm_input_port_p
0f2d19dd 900{
7888309b 901 return scm_from_bool (SCM_INPUT_PORT_P (x));
0f2d19dd 902}
1bbd0b84 903#undef FUNC_NAME
0f2d19dd 904
3b3b36dd 905SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
1bbd0b84 906 (SCM x),
1e6808ea
MG
907 "Return @code{#t} if @var{x} is an output port, otherwise return\n"
908 "@code{#f}. Any object satisfying this predicate also satisfies\n"
909 "@code{port?}.")
1bbd0b84 910#define FUNC_NAME s_scm_output_port_p
0f2d19dd 911{
82893676 912 x = SCM_COERCE_OUTPORT (x);
7888309b 913 return scm_from_bool (SCM_OUTPUT_PORT_P (x));
0f2d19dd 914}
1bbd0b84 915#undef FUNC_NAME
0f2d19dd 916
eb5c0a2a
GH
917SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
918 (SCM x),
1e6808ea 919 "Return a boolean indicating whether @var{x} is a port.\n"
5352393c
MG
920 "Equivalent to @code{(or (input-port? @var{x}) (output-port?\n"
921 "@var{x}))}.")
eb5c0a2a
GH
922#define FUNC_NAME s_scm_port_p
923{
7888309b 924 return scm_from_bool (SCM_PORTP (x));
eb5c0a2a
GH
925}
926#undef FUNC_NAME
927
3b3b36dd 928SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
1bbd0b84 929 (SCM port),
1e6808ea
MG
930 "Return @code{#t} if @var{port} is closed or @code{#f} if it is\n"
931 "open.")
1bbd0b84 932#define FUNC_NAME s_scm_port_closed_p
60d0643d 933{
34d19ef6 934 SCM_VALIDATE_PORT (1, port);
7888309b 935 return scm_from_bool (!SCM_OPPORTP (port));
60d0643d 936}
1bbd0b84 937#undef FUNC_NAME
0f2d19dd 938
3b3b36dd 939SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
1bbd0b84 940 (SCM x),
1e6808ea
MG
941 "Return @code{#t} if @var{x} is an end-of-file object; otherwise\n"
942 "return @code{#f}.")
1bbd0b84 943#define FUNC_NAME s_scm_eof_object_p
0f2d19dd 944{
7888309b 945 return scm_from_bool(SCM_EOF_OBJECT_P (x));
0f2d19dd 946}
1bbd0b84 947#undef FUNC_NAME
0f2d19dd 948
3b3b36dd 949SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
1bbd0b84 950 (SCM port),
b380b885 951 "Flush the specified output port, or the current output port if @var{port}\n"
9401323e 952 "is omitted. The current output buffer contents are passed to the\n"
b380b885
MD
953 "underlying port implementation (e.g., in the case of fports, the\n"
954 "data will be written to the file and the output buffer will be cleared.)\n"
955 "It has no effect on an unbuffered port.\n\n"
956 "The return value is unspecified.")
1bbd0b84 957#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
958{
959 if (SCM_UNBNDP (port))
9de87eea 960 port = scm_current_output_port ();
0f2d19dd 961 else
78446828
MV
962 {
963 port = SCM_COERCE_OUTPORT (port);
34d19ef6 964 SCM_VALIDATE_OPOUTPORT (1, port);
78446828 965 }
affc96b5 966 scm_flush (port);
ee149d03 967 return SCM_UNSPECIFIED;
0f2d19dd 968}
1bbd0b84 969#undef FUNC_NAME
0f2d19dd 970
5dbc6c06
HWN
971
972static void
61d3568b 973flush_output_port (void *closure, SCM port)
5dbc6c06 974{
5dbc6c06
HWN
975 if (SCM_OPOUTPORTP (port))
976 scm_flush (port);
977}
978
a1ec6916 979SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
1bbd0b84 980 (),
b380b885
MD
981 "Equivalent to calling @code{force-output} on\n"
982 "all open output ports. The return value is unspecified.")
1bbd0b84 983#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c 984{
5dbc6c06 985 scm_c_port_for_each (&flush_output_port, NULL);
89ea5b7c
GH
986 return SCM_UNSPECIFIED;
987}
1bbd0b84 988#undef FUNC_NAME
0f2d19dd 989
3b3b36dd 990SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1bbd0b84 991 (SCM port),
1e6808ea
MG
992 "Return the next character available from @var{port}, updating\n"
993 "@var{port} to point to the following character. If no more\n"
994 "characters are available, the end-of-file object is returned.")
1bbd0b84 995#define FUNC_NAME s_scm_read_char
0f2d19dd
JB
996{
997 int c;
998 if (SCM_UNBNDP (port))
9de87eea 999 port = scm_current_input_port ();
34d19ef6 1000 SCM_VALIDATE_OPINPORT (1, port);
b7f3516f 1001 c = scm_getc (port);
0f2d19dd
JB
1002 if (EOF == c)
1003 return SCM_EOF_VAL;
7866a09b 1004 return SCM_MAKE_CHAR (c);
0f2d19dd 1005}
1bbd0b84 1006#undef FUNC_NAME
0f2d19dd 1007
5c070ca7 1008/* this should only be called when the read buffer is empty. it
affc96b5 1009 tries to refill the read buffer. it returns the first char from
5c070ca7 1010 the port, which is either EOF or *(pt->read_pos). */
6c951427 1011int
affc96b5 1012scm_fill_input (SCM port)
6c951427 1013{
92c2555f 1014 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e 1015
b5cb4464
NJ
1016 assert (pt->read_pos == pt->read_end);
1017
6c951427
GH
1018 if (pt->read_buf == pt->putback_buf)
1019 {
1020 /* finished reading put-back chars. */
1021 pt->read_buf = pt->saved_read_buf;
1022 pt->read_pos = pt->saved_read_pos;
1023 pt->read_end = pt->saved_read_end;
1024 pt->read_buf_size = pt->saved_read_buf_size;
1025 if (pt->read_pos < pt->read_end)
5c070ca7 1026 return *(pt->read_pos);
6c951427 1027 }
affc96b5 1028 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
1029}
1030
3cb988bd 1031
6fe692e9
MD
1032/* scm_lfwrite
1033 *
53802ea8
MV
1034 * This function differs from scm_c_write; it updates port line and
1035 * column. */
6fe692e9 1036
ee149d03 1037void
1be6b49c 1038scm_lfwrite (const char *ptr, size_t size, SCM port)
ee149d03 1039{
92c2555f
MV
1040 scm_t_port *pt = SCM_PTAB_ENTRY (port);
1041 scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 1042
840ae05d 1043 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1044 scm_end_input (port);
283a1a0e 1045
31703ab8 1046 ptob->write (port, ptr, size);
840ae05d 1047
53802ea8 1048 for (; size; ptr++, size--) {
a727f4f6
KR
1049 if (*ptr == '\a') {
1050 }
1051 else if (*ptr == '\b') {
1052 SCM_DECCOL(port);
1053 }
1054 else if (*ptr == '\n') {
53802ea8
MV
1055 SCM_INCLINE(port);
1056 }
a727f4f6
KR
1057 else if (*ptr == '\r') {
1058 SCM_ZEROCOL(port);
1059 }
53802ea8
MV
1060 else if (*ptr == '\t') {
1061 SCM_TABCOL(port);
1062 }
1063 else {
1064 SCM_INCCOL(port);
1065 }
1066 }
1067
840ae05d
JB
1068 if (pt->rw_random)
1069 pt->rw_active = SCM_PORT_WRITE;
ee149d03 1070}
3cb988bd 1071
6fe692e9
MD
1072/* scm_c_read
1073 *
1074 * Used by an application to read arbitrary number of bytes from an
1075 * SCM port. Same semantics as libc read, except that scm_c_read only
1076 * returns less than SIZE bytes if at end-of-file.
1077 *
1078 * Warning: Doesn't update port line and column counts! */
1079
b5cb4464
NJ
1080/* This structure, and the following swap_buffer function, are used
1081 for temporarily swapping a port's own read buffer, and the buffer
1082 that the caller of scm_c_read provides. */
1083struct port_and_swap_buffer
1084{
1085 scm_t_port *pt;
1086 unsigned char *buffer;
1087 size_t size;
1088};
1089
1090static void
1091swap_buffer (void *data)
1092{
1093 struct port_and_swap_buffer *psb = (struct port_and_swap_buffer *) data;
1094 unsigned char *old_buf = psb->pt->read_buf;
1095 size_t old_size = psb->pt->read_buf_size;
1096
1097 /* Make the port use (buffer, size) from the struct. */
1098 psb->pt->read_pos = psb->pt->read_buf = psb->pt->read_end = psb->buffer;
1099 psb->pt->read_buf_size = psb->size;
1100
1101 /* Save the port's old (buffer, size) in the struct. */
1102 psb->buffer = old_buf;
1103 psb->size = old_size;
1104}
1105
1be6b49c
ML
1106size_t
1107scm_c_read (SCM port, void *buffer, size_t size)
693758d5 1108#define FUNC_NAME "scm_c_read"
6fe692e9 1109{
693758d5 1110 scm_t_port *pt;
1be6b49c 1111 size_t n_read = 0, n_available;
b5cb4464 1112 struct port_and_swap_buffer psb;
6fe692e9 1113
693758d5
LC
1114 SCM_VALIDATE_OPINPORT (1, port);
1115
1116 pt = SCM_PTAB_ENTRY (port);
6fe692e9
MD
1117 if (pt->rw_active == SCM_PORT_WRITE)
1118 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
1119
1120 if (pt->rw_random)
1121 pt->rw_active = SCM_PORT_READ;
1122
b5cb4464
NJ
1123 /* Take bytes first from the port's read buffer. */
1124 if (pt->read_pos < pt->read_end)
6fe692e9 1125 {
b5cb4464 1126 n_available = min (size, pt->read_end - pt->read_pos);
6fe692e9 1127 memcpy (buffer, pt->read_pos, n_available);
910d1e40 1128 buffer = (char *) buffer + n_available;
6fe692e9
MD
1129 pt->read_pos += n_available;
1130 n_read += n_available;
6fe692e9 1131 size -= n_available;
6fe692e9
MD
1132 }
1133
b5cb4464
NJ
1134 /* Avoid the scm_dynwind_* costs if we now have enough data. */
1135 if (size == 0)
1136 return n_read;
1137
1138 /* Now we will call scm_fill_input repeatedly until we have read the
1139 requested number of bytes. (Note that a single scm_fill_input
1140 call does not guarantee to fill the whole of the port's read
6d227556
NJ
1141 buffer.) */
1142 if (pt->read_buf_size <= 1)
b5cb4464 1143 {
6d227556
NJ
1144 /* The port that we are reading from is unbuffered - i.e. does
1145 not have its own persistent buffer - but we have a buffer,
1146 provided by our caller, that is the right size for the data
1147 that is wanted. For the following scm_fill_input calls,
1148 therefore, we use the buffer in hand as the port's read
1149 buffer.
1150
1151 We need to make sure that the port's normal (1 byte) buffer
1152 is reinstated in case one of the scm_fill_input () calls
1153 throws an exception; we use the scm_dynwind_* API to achieve
1154 that. */
1155 psb.pt = pt;
1156 psb.buffer = buffer;
1157 psb.size = size;
1158 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1159 scm_dynwind_rewind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1160 scm_dynwind_unwind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1161
1162 /* Call scm_fill_input until we have all the bytes that we need,
1163 or we hit EOF. */
1164 while (pt->read_buf_size && (scm_fill_input (port) != EOF))
1165 {
1166 pt->read_buf_size -= (pt->read_end - pt->read_pos);
1167 pt->read_pos = pt->read_buf = pt->read_end;
1168 }
1169 n_read += pt->read_buf - (unsigned char *) buffer;
b5cb4464 1170
6d227556
NJ
1171 /* Reinstate the port's normal buffer. */
1172 scm_dynwind_end ();
1173 }
1174 else
1175 {
1176 /* The port has its own buffer. It is important that we use it,
1177 even if it happens to be smaller than our caller's buffer, so
1178 that a custom port implementation's entry points (in
1179 particular, fill_input) can rely on the buffer always being
1180 the same as they first set up. */
1181 while (size && (scm_fill_input (port) != EOF))
1182 {
1183 n_available = min (size, pt->read_end - pt->read_pos);
1184 memcpy (buffer, pt->read_pos, n_available);
1185 buffer = (char *) buffer + n_available;
1186 pt->read_pos += n_available;
1187 n_read += n_available;
1188 size -= n_available;
1189 }
1190 }
6fe692e9 1191
b5cb4464 1192 return n_read;
6fe692e9 1193}
693758d5 1194#undef FUNC_NAME
6fe692e9
MD
1195
1196/* scm_c_write
1197 *
1198 * Used by an application to write arbitrary number of bytes to an SCM
1199 * port. Similar semantics as libc write. However, unlike libc
1200 * write, scm_c_write writes the requested number of bytes and has no
1201 * return value.
1202 *
1203 * Warning: Doesn't update port line and column counts!
1204 */
1205
693758d5 1206void
1be6b49c 1207scm_c_write (SCM port, const void *ptr, size_t size)
693758d5 1208#define FUNC_NAME "scm_c_write"
6fe692e9 1209{
693758d5
LC
1210 scm_t_port *pt;
1211 scm_t_ptob_descriptor *ptob;
1212
1213 SCM_VALIDATE_OPOUTPORT (1, port);
1214
1215 pt = SCM_PTAB_ENTRY (port);
1216 ptob = &scm_ptobs[SCM_PTOBNUM (port)];
6fe692e9
MD
1217
1218 if (pt->rw_active == SCM_PORT_READ)
1219 scm_end_input (port);
1220
1221 ptob->write (port, ptr, size);
1222
1223 if (pt->rw_random)
1224 pt->rw_active = SCM_PORT_WRITE;
1225}
693758d5 1226#undef FUNC_NAME
3cb988bd 1227
fca43887 1228void
a284e297 1229scm_flush (SCM port)
ee149d03 1230{
c014a02e 1231 long i = SCM_PTOBNUM (port);
7f2a6c38 1232 assert (i >= 0);
affc96b5 1233 (scm_ptobs[i].flush) (port);
ee149d03
JB
1234}
1235
283a1a0e 1236void
a284e297 1237scm_end_input (SCM port)
283a1a0e 1238{
c014a02e 1239 long offset;
92c2555f 1240 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e
GH
1241
1242 if (pt->read_buf == pt->putback_buf)
1243 {
1244 offset = pt->read_end - pt->read_pos;
1245 pt->read_buf = pt->saved_read_buf;
1246 pt->read_pos = pt->saved_read_pos;
1247 pt->read_end = pt->saved_read_end;
1248 pt->read_buf_size = pt->saved_read_buf_size;
1249 }
1250 else
1251 offset = 0;
1252
affc96b5 1253 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
1254}
1255
ee149d03
JB
1256\f
1257
1258
1259void
a284e297 1260scm_ungetc (int c, SCM port)
c6c79933 1261#define FUNC_NAME "scm_ungetc"
ee149d03 1262{
92c2555f 1263 scm_t_port *pt = SCM_PTAB_ENTRY (port);
840ae05d 1264
6c951427
GH
1265 if (pt->read_buf == pt->putback_buf)
1266 /* already using the put-back buffer. */
1267 {
1268 /* enlarge putback_buf if necessary. */
1269 if (pt->read_end == pt->read_buf + pt->read_buf_size
1270 && pt->read_buf == pt->read_pos)
1271 {
1be6b49c 1272 size_t new_size = pt->read_buf_size * 2;
c6c79933 1273 unsigned char *tmp = (unsigned char *)
92d8fd32
LC
1274 /* XXX: Can we use `GC_REALLOC' with `GC_MALLOC_ATOMIC'-allocated
1275 data? (Ludo) */
4c9419ac
MV
1276 scm_gc_realloc (pt->putback_buf, pt->read_buf_size, new_size,
1277 "putback buffer");
6c951427 1278
6c951427
GH
1279 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
1280 pt->read_end = pt->read_buf + pt->read_buf_size;
1281 pt->read_buf_size = pt->putback_buf_size = new_size;
1282 }
1283
1284 /* shift any existing bytes to buffer + 1. */
1285 if (pt->read_pos == pt->read_end)
1286 pt->read_end = pt->read_buf + 1;
1287 else if (pt->read_pos != pt->read_buf + 1)
1288 {
1289 int count = pt->read_end - pt->read_pos;
1290
1291 memmove (pt->read_buf + 1, pt->read_pos, count);
1292 pt->read_end = pt->read_buf + 1 + count;
1293 }
1294
1295 pt->read_pos = pt->read_buf;
1296 }
1297 else
1298 /* switch to the put-back buffer. */
1299 {
1300 if (pt->putback_buf == NULL)
1301 {
c357d546 1302 pt->putback_buf
92d8fd32
LC
1303 = (unsigned char *) scm_gc_malloc_pointerless
1304 (SCM_INITIAL_PUTBACK_BUF_SIZE, "putback buffer");
6c951427
GH
1305 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
1306 }
1307
1308 pt->saved_read_buf = pt->read_buf;
1309 pt->saved_read_pos = pt->read_pos;
1310 pt->saved_read_end = pt->read_end;
1311 pt->saved_read_buf_size = pt->read_buf_size;
1312
1313 pt->read_pos = pt->read_buf = pt->putback_buf;
1314 pt->read_end = pt->read_buf + 1;
1315 pt->read_buf_size = pt->putback_buf_size;
1316 }
1317
1318 *pt->read_buf = c;
ee149d03 1319
840ae05d
JB
1320 if (pt->rw_random)
1321 pt->rw_active = SCM_PORT_READ;
1322
ee149d03
JB
1323 if (c == '\n')
1324 {
1325 /* What should col be in this case?
1326 * We'll leave it at -1.
1327 */
1328 SCM_LINUM (port) -= 1;
1329 }
1330 else
1331 SCM_COL(port) -= 1;
1332}
c6c79933 1333#undef FUNC_NAME
ee149d03
JB
1334
1335
1336void
70d63753 1337scm_ungets (const char *s, int n, SCM port)
ee149d03
JB
1338{
1339 /* This is simple minded and inefficient, but unreading strings is
1340 * probably not a common operation, and remember that line and
1341 * column numbers have to be handled...
1342 *
1343 * Please feel free to write an optimized version!
1344 */
1345 while (n--)
1346 scm_ungetc (s[n], port);
1347}
1348
1349
3b3b36dd 1350SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1bbd0b84 1351 (SCM port),
1e6808ea
MG
1352 "Return the next character available from @var{port},\n"
1353 "@emph{without} updating @var{port} to point to the following\n"
1354 "character. If no more characters are available, the\n"
c2dfff19
KR
1355 "end-of-file object is returned.\n"
1356 "\n"
1357 "The value returned by\n"
1e6808ea
MG
1358 "a call to @code{peek-char} is the same as the value that would\n"
1359 "have been returned by a call to @code{read-char} on the same\n"
1360 "port. The only difference is that the very next call to\n"
1361 "@code{read-char} or @code{peek-char} on that @var{port} will\n"
1362 "return the value returned by the preceding call to\n"
1363 "@code{peek-char}. In particular, a call to @code{peek-char} on\n"
1364 "an interactive port will hang waiting for input whenever a call\n"
c2dfff19 1365 "to @code{read-char} would have hung.")
1bbd0b84 1366#define FUNC_NAME s_scm_peek_char
ee149d03 1367{
1a973c42 1368 int c, column;
ee149d03 1369 if (SCM_UNBNDP (port))
9de87eea 1370 port = scm_current_input_port ();
ee149d03 1371 else
34d19ef6 1372 SCM_VALIDATE_OPINPORT (1, port);
1a973c42 1373 column = SCM_COL(port);
ee149d03
JB
1374 c = scm_getc (port);
1375 if (EOF == c)
1376 return SCM_EOF_VAL;
1377 scm_ungetc (c, port);
1a973c42 1378 SCM_COL(port) = column;
7866a09b 1379 return SCM_MAKE_CHAR (c);
3cb988bd 1380}
1bbd0b84 1381#undef FUNC_NAME
3cb988bd 1382
1be4270a 1383SCM_DEFINE (scm_unread_char, "unread-char", 1, 1, 0,
1bbd0b84 1384 (SCM cobj, SCM port),
b380b885
MD
1385 "Place @var{char} in @var{port} so that it will be read by the\n"
1386 "next read operation. If called multiple times, the unread characters\n"
1387 "will be read again in last-in first-out order. If @var{port} is\n"
1388 "not supplied, the current input port is used.")
1bbd0b84 1389#define FUNC_NAME s_scm_unread_char
0f2d19dd
JB
1390{
1391 int c;
1392
34d19ef6 1393 SCM_VALIDATE_CHAR (1, cobj);
0f2d19dd 1394 if (SCM_UNBNDP (port))
9de87eea 1395 port = scm_current_input_port ();
0f2d19dd 1396 else
34d19ef6 1397 SCM_VALIDATE_OPINPORT (2, port);
0f2d19dd 1398
7866a09b 1399 c = SCM_CHAR (cobj);
0f2d19dd 1400
b7f3516f 1401 scm_ungetc (c, port);
0f2d19dd
JB
1402 return cobj;
1403}
1bbd0b84 1404#undef FUNC_NAME
0f2d19dd 1405
a1ec6916 1406SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1bbd0b84 1407 (SCM str, SCM port),
b380b885
MD
1408 "Place the string @var{str} in @var{port} so that its characters will be\n"
1409 "read in subsequent read operations. If called multiple times, the\n"
1410 "unread characters will be read again in last-in first-out order. If\n"
1411 "@var{port} is not supplied, the current-input-port is used.")
1bbd0b84 1412#define FUNC_NAME s_scm_unread_string
ee1e7e13 1413{
34d19ef6 1414 SCM_VALIDATE_STRING (1, str);
ee1e7e13 1415 if (SCM_UNBNDP (port))
9de87eea 1416 port = scm_current_input_port ();
ee1e7e13 1417 else
34d19ef6 1418 SCM_VALIDATE_OPINPORT (2, port);
ee1e7e13 1419
3a5fb14d 1420 scm_ungets (scm_i_string_chars (str), scm_i_string_length (str), port);
ee1e7e13
MD
1421
1422 return str;
1423}
1bbd0b84 1424#undef FUNC_NAME
ee1e7e13 1425
a1ec6916 1426SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1e6808ea
MG
1427 (SCM fd_port, SCM offset, SCM whence),
1428 "Sets the current position of @var{fd/port} to the integer\n"
1429 "@var{offset}, which is interpreted according to the value of\n"
1430 "@var{whence}.\n"
1431 "\n"
1432 "One of the following variables should be supplied for\n"
1433 "@var{whence}:\n"
b380b885
MD
1434 "@defvar SEEK_SET\n"
1435 "Seek from the beginning of the file.\n"
1436 "@end defvar\n"
1437 "@defvar SEEK_CUR\n"
1438 "Seek from the current position.\n"
1439 "@end defvar\n"
1440 "@defvar SEEK_END\n"
1441 "Seek from the end of the file.\n"
1e6808ea
MG
1442 "@end defvar\n"
1443 "If @var{fd/port} is a file descriptor, the underlying system\n"
1444 "call is @code{lseek}. @var{port} may be a string port.\n"
1445 "\n"
1446 "The value returned is the new position in the file. This means\n"
1447 "that the current position of a port can be obtained using:\n"
1448 "@lisp\n"
b380b885 1449 "(seek port 0 SEEK_CUR)\n"
1e6808ea 1450 "@end lisp")
1bbd0b84 1451#define FUNC_NAME s_scm_seek
840ae05d 1452{
840ae05d
JB
1453 int how;
1454
1e6808ea 1455 fd_port = SCM_COERCE_OUTPORT (fd_port);
840ae05d 1456
a55c2b68 1457 how = scm_to_int (whence);
840ae05d 1458 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1bbd0b84 1459 SCM_OUT_OF_RANGE (3, whence);
23f2b9a3 1460
8ab3d8a0
KR
1461 if (SCM_OPFPORTP (fd_port))
1462 {
1463 /* go direct to fport code to allow 64-bit offsets */
1464 return scm_i_fport_seek (fd_port, offset, how);
1465 }
1466 else if (SCM_OPPORTP (fd_port))
840ae05d 1467 {
92c2555f 1468 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (fd_port);
23f2b9a3
KR
1469 off_t off = scm_to_off_t (offset);
1470 off_t rv;
840ae05d
JB
1471
1472 if (!ptob->seek)
1bbd0b84 1473 SCM_MISC_ERROR ("port is not seekable",
1e6808ea 1474 scm_cons (fd_port, SCM_EOL));
840ae05d 1475 else
1e6808ea 1476 rv = ptob->seek (fd_port, off, how);
23f2b9a3 1477 return scm_from_off_t (rv);
840ae05d
JB
1478 }
1479 else /* file descriptor?. */
1480 {
23f2b9a3
KR
1481 off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1482 off_t_or_off64_t rv;
1483 rv = lseek_or_lseek64 (scm_to_int (fd_port), off, how);
840ae05d 1484 if (rv == -1)
1bbd0b84 1485 SCM_SYSERROR;
23f2b9a3 1486 return scm_from_off_t_or_off64_t (rv);
840ae05d 1487 }
840ae05d 1488}
1bbd0b84 1489#undef FUNC_NAME
840ae05d 1490
8ab3d8a0
KR
1491#ifndef O_BINARY
1492#define O_BINARY 0
1493#endif
1494
1495/* Mingw has ftruncate(), perhaps implemented above using chsize, but
1496 doesn't have the filename version truncate(), hence this code. */
1497#if HAVE_FTRUNCATE && ! HAVE_TRUNCATE
1498static int
1499truncate (const char *file, off_t length)
82893676 1500{
8ab3d8a0
KR
1501 int ret, fdes;
1502
1503 fdes = open (file, O_BINARY | O_WRONLY);
1504 if (fdes == -1)
1505 return -1;
1506
1507 ret = ftruncate (fdes, length);
1508 if (ret == -1)
82893676 1509 {
8ab3d8a0 1510 int save_errno = errno;
82893676 1511 close (fdes);
8ab3d8a0
KR
1512 errno = save_errno;
1513 return -1;
82893676 1514 }
8ab3d8a0
KR
1515
1516 return close (fdes);
82893676 1517}
8ab3d8a0 1518#endif /* HAVE_FTRUNCATE && ! HAVE_TRUNCATE */
82893676 1519
a1ec6916 1520SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1bbd0b84 1521 (SCM object, SCM length),
8ab3d8a0
KR
1522 "Truncate @var{file} to @var{length} bytes. @var{file} can be a\n"
1523 "filename string, a port object, or an integer file descriptor.\n"
1524 "The return value is unspecified.\n"
1525 "\n"
1526 "For a port or file descriptor @var{length} can be omitted, in\n"
1527 "which case the file is truncated at the current position (per\n"
1528 "@code{ftell} above).\n"
1529 "\n"
1530 "On most systems a file can be extended by giving a length\n"
1531 "greater than the current size, but this is not mandatory in the\n"
1532 "POSIX standard.")
1bbd0b84 1533#define FUNC_NAME s_scm_truncate_file
840ae05d 1534{
69bc9ff3 1535 int rv;
69bc9ff3 1536
2b829bbb
KR
1537 /* "object" can be a port, fdes or filename.
1538
1539 Negative "length" makes no sense, but it's left to truncate() or
1540 ftruncate() to give back an error for that (normally EINVAL).
1541 */
840ae05d 1542
840ae05d
JB
1543 if (SCM_UNBNDP (length))
1544 {
69bc9ff3 1545 /* must supply length if object is a filename. */
7f9994d9 1546 if (scm_is_string (object))
34d19ef6 1547 SCM_MISC_ERROR("must supply length if OBJECT is a filename", SCM_EOL);
69bc9ff3 1548
e11e83f3 1549 length = scm_seek (object, SCM_INUM0, scm_from_int (SEEK_CUR));
840ae05d 1550 }
3fe6190f 1551
69bc9ff3 1552 object = SCM_COERCE_OUTPORT (object);
e11e83f3 1553 if (scm_is_integer (object))
69bc9ff3 1554 {
23f2b9a3
KR
1555 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
1556 SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
1557 c_length));
69bc9ff3 1558 }
8ab3d8a0
KR
1559 else if (SCM_OPOUTFPORTP (object))
1560 {
1561 /* go direct to fport code to allow 64-bit offsets */
1562 rv = scm_i_fport_truncate (object, length);
1563 }
0c95b57d 1564 else if (SCM_OPOUTPORTP (object))
69bc9ff3 1565 {
2b829bbb 1566 off_t c_length = scm_to_off_t (length);
92c2555f
MV
1567 scm_t_port *pt = SCM_PTAB_ENTRY (object);
1568 scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1569
affc96b5 1570 if (!ptob->truncate)
1bbd0b84 1571 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1572 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1573 scm_end_input (object);
69bc9ff3 1574 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1575 ptob->flush (object);
69bc9ff3 1576
affc96b5 1577 ptob->truncate (object, c_length);
69bc9ff3
GH
1578 rv = 0;
1579 }
1580 else
1581 {
2b829bbb 1582 off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
7f9994d9
MV
1583 char *str = scm_to_locale_string (object);
1584 int eno;
2b829bbb 1585 SCM_SYSCALL (rv = truncate_or_truncate64 (str, c_length));
7f9994d9
MV
1586 eno = errno;
1587 free (str);
1588 errno = eno;
69bc9ff3
GH
1589 }
1590 if (rv == -1)
1bbd0b84 1591 SCM_SYSERROR;
840ae05d
JB
1592 return SCM_UNSPECIFIED;
1593}
1bbd0b84 1594#undef FUNC_NAME
840ae05d 1595
a1ec6916 1596SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1bbd0b84 1597 (SCM port),
a150979d
KR
1598 "Return the current line number for @var{port}.\n"
1599 "\n"
1600 "The first line of a file is 0. But you might want to add 1\n"
1601 "when printing line numbers, since starting from 1 is\n"
1602 "traditional in error messages, and likely to be more natural to\n"
1603 "non-programmers.")
1bbd0b84 1604#define FUNC_NAME s_scm_port_line
0f2d19dd 1605{
78446828 1606 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1607 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1608 return scm_from_long (SCM_LINUM (port));
0f2d19dd 1609}
1bbd0b84 1610#undef FUNC_NAME
0f2d19dd 1611
a1ec6916 1612SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1bbd0b84 1613 (SCM port, SCM line),
a150979d
KR
1614 "Set the current line number for @var{port} to @var{line}. The\n"
1615 "first line of a file is 0.")
1bbd0b84 1616#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1617{
360fc44c 1618 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1619 SCM_VALIDATE_OPENPORT (1, port);
651f2cd2 1620 SCM_PTAB_ENTRY (port)->line_number = scm_to_long (line);
564478fd 1621 return SCM_UNSPECIFIED;
d043d8c2 1622}
1bbd0b84 1623#undef FUNC_NAME
d043d8c2 1624
a1ec6916 1625SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1bbd0b84 1626 (SCM port),
a150979d
KR
1627 "Return the current column number of @var{port}.\n"
1628 "If the number is\n"
b380b885
MD
1629 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1630 "- i.e. the first character of the first line is line 0, column 0.\n"
1631 "(However, when you display a file position, for example in an error\n"
650a1cf9 1632 "message, we recommend you add 1 to get 1-origin integers. This is\n"
b380b885
MD
1633 "because lines and column numbers traditionally start with 1, and that is\n"
1634 "what non-programmers will find most natural.)")
1bbd0b84 1635#define FUNC_NAME s_scm_port_column
0f2d19dd 1636{
78446828 1637 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1638 SCM_VALIDATE_OPENPORT (1, port);
e11e83f3 1639 return scm_from_int (SCM_COL (port));
0f2d19dd 1640}
1bbd0b84 1641#undef FUNC_NAME
0f2d19dd 1642
a1ec6916 1643SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1bbd0b84 1644 (SCM port, SCM column),
a150979d
KR
1645 "Set the current column of @var{port}. Before reading the first\n"
1646 "character on a line the column should be 0.")
1bbd0b84 1647#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1648{
360fc44c 1649 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1650 SCM_VALIDATE_OPENPORT (1, port);
a55c2b68 1651 SCM_PTAB_ENTRY (port)->column_number = scm_to_int (column);
564478fd 1652 return SCM_UNSPECIFIED;
d043d8c2 1653}
1bbd0b84 1654#undef FUNC_NAME
d043d8c2 1655
a1ec6916 1656SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1bbd0b84 1657 (SCM port),
b380b885 1658 "Return the filename associated with @var{port}. This function returns\n"
2a2a730b 1659 "the strings \"standard input\", \"standard output\" and \"standard error\"\n"
a3c8b9fc 1660 "when called on the current input, output and error ports respectively.")
1bbd0b84 1661#define FUNC_NAME s_scm_port_filename
0f2d19dd 1662{
78446828 1663 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1664 SCM_VALIDATE_OPENPORT (1, port);
b24b5e13 1665 return SCM_FILENAME (port);
0f2d19dd 1666}
1bbd0b84 1667#undef FUNC_NAME
0f2d19dd 1668
a1ec6916 1669SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1bbd0b84 1670 (SCM port, SCM filename),
b380b885
MD
1671 "Change the filename associated with @var{port}, using the current input\n"
1672 "port if none is specified. Note that this does not change the port's\n"
1673 "source of data, but only the value that is returned by\n"
1674 "@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1675#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1676{
360fc44c 1677 port = SCM_COERCE_OUTPORT (port);
34d19ef6 1678 SCM_VALIDATE_OPENPORT (1, port);
360fc44c 1679 /* We allow the user to set the filename to whatever he likes. */
b24b5e13
DH
1680 SCM_SET_FILENAME (port, filename);
1681 return SCM_UNSPECIFIED;
d14af9f2 1682}
1bbd0b84 1683#undef FUNC_NAME
d14af9f2 1684
f12733c9
MD
1685void
1686scm_print_port_mode (SCM exp, SCM port)
1687{
1688 scm_puts (SCM_CLOSEDP (exp)
1689 ? "closed: "
f9a64404
DH
1690 : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
1691 ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1692 ? "input-output: "
1693 : "input: ")
f9a64404 1694 : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1695 ? "output: "
1696 : "bogus: ")),
1697 port);
1698}
1cc91f1b 1699
f12733c9 1700int
e81d98ec 1701scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 1702{
f12733c9
MD
1703 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1704 if (!type)
1705 type = "port";
b7f3516f 1706 scm_puts ("#<", port);
f12733c9 1707 scm_print_port_mode (exp, port);
b7f3516f
TT
1708 scm_puts (type, port);
1709 scm_putc (' ', port);
0345e278 1710 scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
b7f3516f 1711 scm_putc ('>', port);
f12733c9 1712 return 1;
0f2d19dd
JB
1713}
1714
0f2d19dd
JB
1715void
1716scm_ports_prehistory ()
0f2d19dd
JB
1717{
1718 scm_numptob = 0;
fca43887 1719 scm_ptobs = NULL;
0f2d19dd 1720}
0f2d19dd
JB
1721
1722\f
ee149d03 1723
d68fee48 1724/* Void ports. */
0f2d19dd 1725
92c2555f 1726scm_t_bits scm_tc16_void_port = 0;
0f2d19dd 1727
e81d98ec 1728static int fill_input_void_port (SCM port SCM_UNUSED)
283a1a0e 1729{
70df8af6 1730 return EOF;
283a1a0e
GH
1731}
1732
31703ab8 1733static void
e81d98ec
DH
1734write_void_port (SCM port SCM_UNUSED,
1735 const void *data SCM_UNUSED,
1736 size_t size SCM_UNUSED)
31703ab8
GH
1737{
1738}
1739
d617ee18
MV
1740static SCM
1741scm_i_void_port (long mode_bits)
0f2d19dd 1742{
9de87eea 1743 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
402788a9 1744 {
da220f27
HWN
1745 SCM answer = scm_new_port_table_entry (scm_tc16_void_port);
1746 scm_t_port * pt = SCM_PTAB_ENTRY(answer);
1747
402788a9 1748 scm_port_non_buffer (pt);
402788a9
HWN
1749
1750 SCM_SETSTREAM (answer, 0);
1751 SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
9de87eea 1752 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
402788a9
HWN
1753 return answer;
1754 }
0f2d19dd
JB
1755}
1756
d617ee18
MV
1757SCM
1758scm_void_port (char *mode_str)
1759{
1760 return scm_i_void_port (scm_mode_bits (mode_str));
1761}
1762
a1ec6916 1763SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 1764 (SCM mode),
70df8af6 1765 "Create and return a new void port. A void port acts like\n"
bb2c02f2 1766 "@file{/dev/null}. The @var{mode} argument\n"
70df8af6 1767 "specifies the input/output modes for this port: see the\n"
b380b885 1768 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1769#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1770{
d617ee18 1771 return scm_i_void_port (scm_i_mode_bits (mode));
0f2d19dd 1772}
1bbd0b84 1773#undef FUNC_NAME
0f2d19dd 1774
0f2d19dd 1775\f
89545eba 1776/* Initialization. */
1cc91f1b 1777
0f2d19dd
JB
1778void
1779scm_init_ports ()
0f2d19dd 1780{
840ae05d 1781 /* lseek() symbols. */
e11e83f3
MV
1782 scm_c_define ("SEEK_SET", scm_from_int (SEEK_SET));
1783 scm_c_define ("SEEK_CUR", scm_from_int (SEEK_CUR));
1784 scm_c_define ("SEEK_END", scm_from_int (SEEK_END));
840ae05d 1785
70df8af6
GH
1786 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
1787 write_void_port);
9de87eea
MV
1788
1789 cur_inport_fluid = scm_permanent_object (scm_make_fluid ());
1790 cur_outport_fluid = scm_permanent_object (scm_make_fluid ());
1791 cur_errport_fluid = scm_permanent_object (scm_make_fluid ());
1792 cur_loadport_fluid = scm_permanent_object (scm_make_fluid ());
1793
5dbc6c06
HWN
1794 scm_i_port_weak_hash = scm_permanent_object (scm_make_weak_key_hash_table (SCM_I_MAKINUM(31)));
1795
a0599745 1796#include "libguile/ports.x"
0f2d19dd 1797}
89e00824
ML
1798
1799/*
1800 Local Variables:
1801 c-file-style: "gnu"
1802 End:
1803*/