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