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