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