*** empty log message ***
[bpt/guile.git] / libguile / ports.c
CommitLineData
be54b15d 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001 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
1cc91f1b 434
da220f27
HWN
435SCM
436scm_new_port_table_entry (scm_t_bits tag)
402788a9 437#define FUNC_NAME "scm_new_port_table_entry"
0f2d19dd 438{
85835e59
HWN
439 /*
440 We initialize the cell to empty, this is in case scm_gc_calloc
441 triggers GC ; we don't want the GC to scan a half-finished Z.
442 */
443
67329a9e 444 SCM z = scm_cons (SCM_EOL, SCM_EOL);
39e8f371 445 scm_t_port *entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
67329a9e 446 if (scm_i_port_table_size == scm_i_port_table_room)
0f2d19dd 447 {
4c9419ac 448 /* initial malloc is in gc.c. this doesn't use scm_gc_malloc etc.,
c6c79933 449 since it can never be freed during gc. */
67329a9e 450 void *newt = scm_realloc ((char *) scm_i_port_table,
4c9419ac 451 (size_t) (sizeof (scm_t_port *)
67329a9e
HWN
452 * scm_i_port_table_room * 2));
453 scm_i_port_table = (scm_t_port **) newt;
454 scm_i_port_table_room *= 2;
0f2d19dd 455 }
840ae05d 456
67329a9e 457 entry->entry = scm_i_port_table_size;
5f16b897 458
840ae05d 459 entry->file_name = SCM_BOOL_F;
61e452ba 460 entry->rw_active = SCM_PORT_NEITHER;
5f16b897 461
67329a9e
HWN
462 scm_i_port_table[scm_i_port_table_size] = entry;
463 scm_i_port_table_size++;
840ae05d 464
da220f27
HWN
465 entry->port = z;
466 SCM_SET_CELL_TYPE(z, tag);
467 SCM_SETPTAB_ENTRY(z, entry);
468
469 return z;
0f2d19dd 470}
c6c79933 471#undef FUNC_NAME
0f2d19dd 472
67329a9e
HWN
473#if SCM_ENABLE_DEPRECATED==1
474SCM_API scm_t_port *
475scm_add_to_port_table (SCM port)
476{
477 SCM z = scm_new_port_table_entry (scm_tc7_port);
478 scm_t_port * pt = SCM_PTAB_ENTRY(z);
479
480 pt->port = port;
481 SCM_SETCAR(z, SCM_EOL);
482 SCM_SETCDR(z, SCM_EOL);
85835e59 483 SCM_SETPTAB_ENTRY (port, pt);
67329a9e
HWN
484 return pt;
485}
486#endif
487
488
6c951427 489/* Remove a port from the table and destroy it. */
0f2d19dd 490void
a284e297 491scm_remove_from_port_table (SCM port)
db4b4ca6 492#define FUNC_NAME "scm_remove_from_port_table"
0f2d19dd 493{
92c2555f 494 scm_t_port *p = SCM_PTAB_ENTRY (port);
c014a02e 495 long i = p->entry;
6c951427 496
67329a9e 497 if (i >= scm_i_port_table_size)
1afff620 498 SCM_MISC_ERROR ("Port not in table: ~S", scm_list_1 (port));
6c951427 499 if (p->putback_buf)
4c9419ac
MV
500 scm_gc_free (p->putback_buf, p->putback_buf_size, "putback buffer");
501 scm_gc_free (p, sizeof (scm_t_port), "port");
ee1e7e13
MD
502 /* Since we have just freed slot i we can shrink the table by moving
503 the last entry to that slot... */
67329a9e 504 if (i < scm_i_port_table_size - 1)
0f2d19dd 505 {
67329a9e
HWN
506 scm_i_port_table[i] = scm_i_port_table[scm_i_port_table_size - 1];
507 scm_i_port_table[i]->entry = i;
0f2d19dd 508 }
0f2d19dd 509 SCM_SETPTAB_ENTRY (port, 0);
67329a9e 510 scm_i_port_table_size--;
0f2d19dd 511}
db4b4ca6
DH
512#undef FUNC_NAME
513
0f2d19dd 514
fea6b4ea 515#ifdef GUILE_DEBUG
b450f070 516/* Functions for debugging. */
1cc91f1b 517
3b3b36dd 518SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
b450f070 519 (),
1e6808ea 520 "Return the number of ports in the port table. @code{pt-size}\n"
5352393c 521 "is only included in @code{--enable-guile-debug} builds.")
1bbd0b84 522#define FUNC_NAME s_scm_pt_size
0f2d19dd 523{
67329a9e 524 return SCM_MAKINUM (scm_i_port_table_size);
0f2d19dd 525}
1bbd0b84 526#undef FUNC_NAME
0f2d19dd 527
3b3b36dd 528SCM_DEFINE (scm_pt_member, "pt-member", 1, 0, 0,
b450f070 529 (SCM index),
1e6808ea 530 "Return the port at @var{index} in the port table.\n"
5352393c
MG
531 "@code{pt-member} is only included in\n"
532 "@code{--enable-guile-debug} builds.")
1bbd0b84 533#define FUNC_NAME s_scm_pt_member
0f2d19dd 534{
c014a02e 535 long i;
34d19ef6 536 SCM_VALIDATE_INUM_COPY (1, index, i);
67329a9e 537 if (i < 0 || i >= scm_i_port_table_size)
0f2d19dd
JB
538 return SCM_BOOL_F;
539 else
67329a9e 540 return scm_i_port_table[i]->port;
0f2d19dd 541}
1bbd0b84 542#undef FUNC_NAME
0f2d19dd
JB
543#endif
544
70df8af6 545void
92c2555f 546scm_port_non_buffer (scm_t_port *pt)
70df8af6
GH
547{
548 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
549 pt->write_buf = pt->write_pos = &pt->shortbuf;
550 pt->read_buf_size = pt->write_buf_size = 1;
551 pt->write_end = pt->write_buf + pt->write_buf_size;
552}
0f2d19dd 553
d68fee48
JB
554\f
555/* Revealed counts --- an oddity inherited from SCSH. */
556
8b13c6b3
GH
557/* Find a port in the table and return its revealed count.
558 Also used by the garbage collector.
0f2d19dd 559 */
1cc91f1b 560
0f2d19dd 561int
a284e297 562scm_revealed_count (SCM port)
0f2d19dd
JB
563{
564 return SCM_REVEALED(port);
565}
566
567
568
569/* Return the revealed count for a port. */
570
3b3b36dd 571SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
1bbd0b84 572 (SCM port),
1e6808ea 573 "Return the revealed count for @var{port}.")
1bbd0b84 574#define FUNC_NAME s_scm_port_revealed
0f2d19dd 575{
78446828 576 port = SCM_COERCE_OUTPORT (port);
34d19ef6 577 SCM_VALIDATE_OPENPORT (1, port);
8b13c6b3 578 return SCM_MAKINUM (scm_revealed_count (port));
0f2d19dd 579}
1bbd0b84 580#undef FUNC_NAME
0f2d19dd
JB
581
582/* Set the revealed count for a port. */
3b3b36dd 583SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
1bbd0b84 584 (SCM port, SCM rcount),
b450f070 585 "Sets the revealed count for a port to a given value.\n"
b380b885 586 "The return value is unspecified.")
1bbd0b84 587#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 588{
78446828 589 port = SCM_COERCE_OUTPORT (port);
34d19ef6
HWN
590 SCM_VALIDATE_OPENPORT (1, port);
591 SCM_VALIDATE_INUM (2, rcount);
0f2d19dd 592 SCM_REVEALED (port) = SCM_INUM (rcount);
8b13c6b3 593 return SCM_UNSPECIFIED;
0f2d19dd 594}
1bbd0b84 595#undef FUNC_NAME
0f2d19dd 596
d68fee48
JB
597
598\f
599/* Retrieving a port's mode. */
600
eadd48de
GH
601/* Return the flags that characterize a port based on the mode
602 * string used to open a file for that port.
603 *
604 * See PORT FLAGS in scm.h
605 */
606
607long
a284e297 608scm_mode_bits (char *modes)
eadd48de
GH
609{
610 return (SCM_OPN
611 | (strchr (modes, 'r') || strchr (modes, '+') ? SCM_RDNG : 0)
612 | ( strchr (modes, 'w')
613 || strchr (modes, 'a')
614 || strchr (modes, '+') ? SCM_WRTNG : 0)
ee149d03
JB
615 | (strchr (modes, '0') ? SCM_BUF0 : 0)
616 | (strchr (modes, 'l') ? SCM_BUFLINE : 0));
eadd48de
GH
617}
618
619
620/* Return the mode flags from an open port.
621 * Some modes such as "append" are only used when opening
622 * a file and are not returned here. */
623
3b3b36dd 624SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
1bbd0b84 625 (SCM port),
1e6808ea
MG
626 "Return the port modes associated with the open port @var{port}.\n"
627 "These will not necessarily be identical to the modes used when\n"
628 "the port was opened, since modes such as \"append\" which are\n"
629 "used only during port creation are not retained.")
1bbd0b84 630#define FUNC_NAME s_scm_port_mode
eadd48de 631{
26a3038d 632 char modes[4];
eadd48de 633 modes[0] = '\0';
78446828
MV
634
635 port = SCM_COERCE_OUTPORT (port);
34d19ef6 636 SCM_VALIDATE_OPPORT (1, port);
f9a64404
DH
637 if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
638 if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de
GH
639 strcpy (modes, "r+");
640 else
641 strcpy (modes, "r");
642 }
f9a64404 643 else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de 644 strcpy (modes, "w");
f9a64404 645 if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
eadd48de 646 strcat (modes, "0");
36284627 647 return scm_mem2string (modes, strlen (modes));
eadd48de 648}
1bbd0b84 649#undef FUNC_NAME
eadd48de
GH
650
651
d68fee48
JB
652\f
653/* Closing ports. */
654
0f2d19dd
JB
655/* scm_close_port
656 * Call the close operation on a port object.
eadd48de 657 * see also scm_close.
0f2d19dd 658 */
3b3b36dd 659SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
1bbd0b84 660 (SCM port),
1e6808ea
MG
661 "Close the specified port object. Return @code{#t} if it\n"
662 "successfully closes a port or @code{#f} if it was already\n"
663 "closed. An exception may be raised if an error occurs, for\n"
664 "example when flushing buffered output. See also @ref{Ports and\n"
665 "File Descriptors, close}, for a procedure which can close file\n"
666 "descriptors.")
1bbd0b84 667#define FUNC_NAME s_scm_close_port
0f2d19dd 668{
1be6b49c 669 size_t i;
eadd48de
GH
670 int rv;
671
78446828
MV
672 port = SCM_COERCE_OUTPORT (port);
673
7a754ca6 674 SCM_VALIDATE_PORT (1, port);
0f2d19dd 675 if (SCM_CLOSEDP (port))
eadd48de 676 return SCM_BOOL_F;
0f2d19dd 677 i = SCM_PTOBNUM (port);
affc96b5
GH
678 if (scm_ptobs[i].close)
679 rv = (scm_ptobs[i].close) (port);
eadd48de
GH
680 else
681 rv = 0;
0f2d19dd 682 scm_remove_from_port_table (port);
22a52da1 683 SCM_CLR_PORT_OPEN_FLAG (port);
36284627 684 return SCM_BOOL (rv >= 0);
7a754ca6
MD
685}
686#undef FUNC_NAME
687
688SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
689 (SCM port),
690 "Close the specified input port object. The routine has no effect if\n"
691 "the file has already been closed. An exception may be raised if an\n"
692 "error occurs. The value returned is unspecified.\n\n"
693 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
694 "which can close file descriptors.")
695#define FUNC_NAME s_scm_close_input_port
696{
697 SCM_VALIDATE_INPUT_PORT (1, port);
698 scm_close_port (port);
699 return SCM_UNSPECIFIED;
700}
701#undef FUNC_NAME
702
703SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
704 (SCM port),
705 "Close the specified output port object. The routine has no effect if\n"
706 "the file has already been closed. An exception may be raised if an\n"
707 "error occurs. The value returned is unspecified.\n\n"
708 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
709 "which can close file descriptors.")
710#define FUNC_NAME s_scm_close_output_port
711{
712 port = SCM_COERCE_OUTPORT (port);
713 SCM_VALIDATE_OUTPUT_PORT (1, port);
714 scm_close_port (port);
715 return SCM_UNSPECIFIED;
0f2d19dd 716}
1bbd0b84 717#undef FUNC_NAME
0f2d19dd 718
c2ca4493
GH
719SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
720 (SCM proc),
721 "Apply @var{proc} to each port in the Guile port table\n"
2f1bbcfd
MV
722 "in turn. The return value is unspecified. More specifically,\n"
723 "@var{proc} is applied exactly once to every port that exists\n"
724 "in the system at the time @var{port-for-each} is invoked.\n"
725 "Changes to the port table while @var{port-for-each} is running\n"
9401323e 726 "have no effect as far as @var{port-for-each} is concerned.")
c2ca4493
GH
727#define FUNC_NAME s_scm_port_for_each
728{
c014a02e 729 long i;
fdfe6305
MV
730 SCM ports;
731
c2ca4493
GH
732 SCM_VALIDATE_PROC (1, proc);
733
734 /* when pre-emptive multithreading is supported, access to the port
735 table will need to be controlled by a mutex. */
fdfe6305
MV
736
737 /* Even without pre-emptive multithreading, running arbitrary code
738 while scanning the port table is unsafe because the port table
739 can change arbitrarily (from a GC, for example). So we build a
740 list in advance while blocking the GC. -mvo */
741
c2ca4493 742 SCM_DEFER_INTS;
fdfe6305
MV
743 scm_block_gc++;
744 ports = SCM_EOL;
67329a9e
HWN
745 for (i = 0; i < scm_i_port_table_size; i++)
746 ports = scm_cons (scm_i_port_table[i]->port, ports);
fdfe6305
MV
747 scm_block_gc--;
748 SCM_ALLOW_INTS;
749
750 while (ports != SCM_EOL)
c2ca4493 751 {
fdc28395 752 scm_call_1 (proc, SCM_CAR (ports));
fdfe6305 753 ports = SCM_CDR (ports);
c2ca4493 754 }
fdfe6305 755
c2ca4493
GH
756 return SCM_UNSPECIFIED;
757}
758#undef FUNC_NAME
759
d68fee48
JB
760\f
761/* Utter miscellany. Gosh, we should clean this up some time. */
762
3b3b36dd 763SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
1bbd0b84 764 (SCM x),
1e6808ea
MG
765 "Return @code{#t} if @var{x} is an input port, otherwise return\n"
766 "@code{#f}. Any object satisfying this predicate also satisfies\n"
767 "@code{port?}.")
1bbd0b84 768#define FUNC_NAME s_scm_input_port_p
0f2d19dd 769{
36284627 770 return SCM_BOOL (SCM_INPUT_PORT_P (x));
0f2d19dd 771}
1bbd0b84 772#undef FUNC_NAME
0f2d19dd 773
3b3b36dd 774SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
1bbd0b84 775 (SCM x),
1e6808ea
MG
776 "Return @code{#t} if @var{x} is an output 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_output_port_p
0f2d19dd 780{
82893676 781 x = SCM_COERCE_OUTPORT (x);
36284627 782 return SCM_BOOL (SCM_OUTPUT_PORT_P (x));
0f2d19dd 783}
1bbd0b84 784#undef FUNC_NAME
0f2d19dd 785
eb5c0a2a
GH
786SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
787 (SCM x),
1e6808ea 788 "Return a boolean indicating whether @var{x} is a port.\n"
5352393c
MG
789 "Equivalent to @code{(or (input-port? @var{x}) (output-port?\n"
790 "@var{x}))}.")
eb5c0a2a
GH
791#define FUNC_NAME s_scm_port_p
792{
793 return SCM_BOOL (SCM_PORTP (x));
794}
795#undef FUNC_NAME
796
3b3b36dd 797SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
1bbd0b84 798 (SCM port),
1e6808ea
MG
799 "Return @code{#t} if @var{port} is closed or @code{#f} if it is\n"
800 "open.")
1bbd0b84 801#define FUNC_NAME s_scm_port_closed_p
60d0643d 802{
34d19ef6 803 SCM_VALIDATE_PORT (1, port);
36284627 804 return SCM_BOOL (!SCM_OPPORTP (port));
60d0643d 805}
1bbd0b84 806#undef FUNC_NAME
0f2d19dd 807
3b3b36dd 808SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
1bbd0b84 809 (SCM x),
1e6808ea
MG
810 "Return @code{#t} if @var{x} is an end-of-file object; otherwise\n"
811 "return @code{#f}.")
1bbd0b84 812#define FUNC_NAME s_scm_eof_object_p
0f2d19dd 813{
1bbd0b84 814 return SCM_BOOL(SCM_EOF_OBJECT_P (x));
0f2d19dd 815}
1bbd0b84 816#undef FUNC_NAME
0f2d19dd 817
3b3b36dd 818SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
1bbd0b84 819 (SCM port),
b380b885 820 "Flush the specified output port, or the current output port if @var{port}\n"
9401323e 821 "is omitted. The current output buffer contents are passed to the\n"
b380b885
MD
822 "underlying port implementation (e.g., in the case of fports, the\n"
823 "data will be written to the file and the output buffer will be cleared.)\n"
824 "It has no effect on an unbuffered port.\n\n"
825 "The return value is unspecified.")
1bbd0b84 826#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
827{
828 if (SCM_UNBNDP (port))
3e877d15 829 port = scm_cur_outp;
0f2d19dd 830 else
78446828
MV
831 {
832 port = SCM_COERCE_OUTPORT (port);
34d19ef6 833 SCM_VALIDATE_OPOUTPORT (1, port);
78446828 834 }
affc96b5 835 scm_flush (port);
ee149d03 836 return SCM_UNSPECIFIED;
0f2d19dd 837}
1bbd0b84 838#undef FUNC_NAME
0f2d19dd 839
a1ec6916 840SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
1bbd0b84 841 (),
b380b885
MD
842 "Equivalent to calling @code{force-output} on\n"
843 "all open output ports. The return value is unspecified.")
1bbd0b84 844#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c 845{
1be6b49c 846 size_t i;
89ea5b7c 847
67329a9e 848 for (i = 0; i < scm_i_port_table_size; i++)
89ea5b7c 849 {
67329a9e
HWN
850 if (SCM_OPOUTPORTP (scm_i_port_table[i]->port))
851 scm_flush (scm_i_port_table[i]->port);
89ea5b7c
GH
852 }
853 return SCM_UNSPECIFIED;
854}
1bbd0b84 855#undef FUNC_NAME
0f2d19dd 856
3b3b36dd 857SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1bbd0b84 858 (SCM port),
1e6808ea
MG
859 "Return the next character available from @var{port}, updating\n"
860 "@var{port} to point to the following character. If no more\n"
861 "characters are available, the end-of-file object is returned.")
1bbd0b84 862#define FUNC_NAME s_scm_read_char
0f2d19dd
JB
863{
864 int c;
865 if (SCM_UNBNDP (port))
334341aa 866 port = scm_cur_inp;
34d19ef6 867 SCM_VALIDATE_OPINPORT (1, port);
b7f3516f 868 c = scm_getc (port);
0f2d19dd
JB
869 if (EOF == c)
870 return SCM_EOF_VAL;
7866a09b 871 return SCM_MAKE_CHAR (c);
0f2d19dd 872}
1bbd0b84 873#undef FUNC_NAME
0f2d19dd 874
5c070ca7 875/* this should only be called when the read buffer is empty. it
affc96b5 876 tries to refill the read buffer. it returns the first char from
5c070ca7 877 the port, which is either EOF or *(pt->read_pos). */
6c951427 878int
affc96b5 879scm_fill_input (SCM port)
6c951427 880{
92c2555f 881 scm_t_port *pt = SCM_PTAB_ENTRY (port);
283a1a0e 882
6c951427
GH
883 if (pt->read_buf == pt->putback_buf)
884 {
885 /* finished reading put-back chars. */
886 pt->read_buf = pt->saved_read_buf;
887 pt->read_pos = pt->saved_read_pos;
888 pt->read_end = pt->saved_read_end;
889 pt->read_buf_size = pt->saved_read_buf_size;
890 if (pt->read_pos < pt->read_end)
5c070ca7 891 return *(pt->read_pos);
6c951427 892 }
affc96b5 893 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
894}
895
ee149d03 896int
a284e297 897scm_getc (SCM port)
0f2d19dd
JB
898{
899 int c;
92c2555f 900 scm_t_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 901
840ae05d 902 if (pt->rw_active == SCM_PORT_WRITE)
aab1caad
RB
903 /* may be marginally faster than calling scm_flush. */
904 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
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
aab1caad 917 switch (c)
ee149d03 918 {
aab1caad
RB
919 case '\n':
920 SCM_INCLINE (port);
921 break;
922 case '\t':
923 SCM_TABCOL (port);
924 break;
925 default:
926 SCM_INCCOL (port);
927 break;
ee149d03 928 }
aab1caad 929
ee149d03 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;
67329a9e 1499 scm_ptobs = (scm_t_ptob_descriptor *) scm_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);
da220f27
HWN
1526 SCM answer = scm_new_port_table_entry (scm_tc16_void_port);
1527 scm_t_port * pt = SCM_PTAB_ENTRY(answer);
1528
402788a9 1529 scm_port_non_buffer (pt);
402788a9
HWN
1530
1531 SCM_SETSTREAM (answer, 0);
1532 SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
1533 SCM_ALLOW_INTS;
1534 return answer;
1535 }
0f2d19dd
JB
1536}
1537
a1ec6916 1538SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 1539 (SCM mode),
70df8af6 1540 "Create and return a new void port. A void port acts like\n"
bb2c02f2 1541 "@file{/dev/null}. The @var{mode} argument\n"
70df8af6 1542 "specifies the input/output modes for this port: see the\n"
b380b885 1543 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1544#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1545{
a6d9e5ab 1546 SCM_VALIDATE_STRING (1, mode);
a6d9e5ab 1547 return scm_void_port (SCM_STRING_CHARS (mode));
0f2d19dd 1548}
1bbd0b84 1549#undef FUNC_NAME
0f2d19dd 1550
0f2d19dd 1551\f
89545eba 1552/* Initialization. */
1cc91f1b 1553
0f2d19dd
JB
1554void
1555scm_init_ports ()
0f2d19dd 1556{
840ae05d 1557 /* lseek() symbols. */
86d31dfe
MV
1558 scm_c_define ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1559 scm_c_define ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1560 scm_c_define ("SEEK_END", SCM_MAKINUM (SEEK_END));
840ae05d 1561
70df8af6
GH
1562 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
1563 write_void_port);
a0599745 1564#include "libguile/ports.x"
0f2d19dd 1565}
89e00824
ML
1566
1567/*
1568 Local Variables:
1569 c-file-style: "gnu"
1570 End:
1571*/