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