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