* Deprecated macros SCM_ROCHARS and SCM_ROUCHARS.
[bpt/guile.git] / libguile / ports.c
CommitLineData
7a754ca6 1/* Copyright (C) 1995,1996,1997,1998,1999, 2000 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
0f2d19dd 118long
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
6c951427 275/* Clear a port's read buffers, returning the contents. */
a1ec6916 276SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
1bbd0b84 277 (SCM port),
b380b885
MD
278 "Drains @var{PORT}'s read buffers (including any pushed-back characters)\n"
279 "and returns the contents as a single string.")
1bbd0b84 280#define FUNC_NAME s_scm_drain_input
ee149d03 281{
840ae05d
JB
282 SCM result;
283 scm_port *pt = SCM_PTAB_ENTRY (port);
6c951427 284 int count;
840ae05d 285 char *dst;
ee149d03 286
3b3b36dd 287 SCM_VALIDATE_OPINPORT (1,port);
840ae05d 288
6c951427
GH
289 count = pt->read_end - pt->read_pos;
290 if (pt->read_buf == pt->putback_buf)
291 count += pt->saved_read_end - pt->saved_read_pos;
840ae05d 292
6c951427 293 result = scm_makstr (count, 0);
86c991c2 294 dst = SCM_STRING_CHARS (result);
840ae05d
JB
295
296 while (pt->read_pos < pt->read_end)
6c951427
GH
297 *dst++ = *(pt->read_pos++);
298
299 if (pt->read_buf == pt->putback_buf)
840ae05d 300 {
6c951427
GH
301 while (pt->saved_read_pos < pt->saved_read_end)
302 *dst++ = *(pt->saved_read_pos++);
840ae05d 303 }
6c951427 304
840ae05d 305 return result;
ee149d03 306}
1bbd0b84 307#undef FUNC_NAME
0f2d19dd
JB
308
309\f
d68fee48 310/* Standard ports --- current input, output, error, and more(!). */
0f2d19dd 311
3b3b36dd 312SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
1bbd0b84 313 (),
bfc46627
GB
314 "Returns the current input port. This is the default port used by many\n"
315 "input procedures. Initially, @code{current-input-port} returns the\n"
316 "value of @code{???}.")
1bbd0b84 317#define FUNC_NAME s_scm_current_input_port
0f2d19dd
JB
318{
319 return scm_cur_inp;
320}
1bbd0b84 321#undef FUNC_NAME
0f2d19dd 322
3b3b36dd 323SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
1bbd0b84 324 (),
bfc46627
GB
325 "Returns the current output port. This is the default port used by many\n"
326 "output procedures. Initially, @code{current-output-port} returns the\n"
327 "value of @code{???}.")
1bbd0b84 328#define FUNC_NAME s_scm_current_output_port
0f2d19dd
JB
329{
330 return scm_cur_outp;
331}
1bbd0b84 332#undef FUNC_NAME
0f2d19dd 333
3b3b36dd 334SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
1bbd0b84 335 (),
b380b885
MD
336 "Return the port to which errors and warnings should be sent (the\n"
337 "@dfn{standard error} in Unix and C terminology).")
1bbd0b84 338#define FUNC_NAME s_scm_current_error_port
0f2d19dd
JB
339{
340 return scm_cur_errp;
341}
1bbd0b84 342#undef FUNC_NAME
0f2d19dd 343
3b3b36dd 344SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
1bbd0b84 345 (),
b450f070
GB
346 "Return the current-load-port.\n"
347 "The load port is used internally by `primitive-load'.")
1bbd0b84 348#define FUNC_NAME s_scm_current_load_port
31614d8e
MD
349{
350 return scm_cur_loadp;
351}
1bbd0b84 352#undef FUNC_NAME
31614d8e 353
3b3b36dd 354SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
1bbd0b84 355 (SCM port),
b380b885
MD
356 "@deffnx primitive set-current-output-port port\n"
357 "@deffnx primitive set-current-error-port port\n"
358 "Change the ports returned by @code{current-input-port},\n"
359 "@code{current-output-port} and @code{current-error-port}, respectively,\n"
360 "so that they use the supplied @var{port} for input or output.")
1bbd0b84 361#define FUNC_NAME s_scm_set_current_input_port
0f2d19dd
JB
362{
363 SCM oinp = scm_cur_inp;
3b3b36dd 364 SCM_VALIDATE_OPINPORT (1,port);
0f2d19dd
JB
365 scm_cur_inp = port;
366 return oinp;
367}
1bbd0b84 368#undef FUNC_NAME
0f2d19dd
JB
369
370
3b3b36dd 371SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
1bbd0b84 372 (SCM port),
b450f070 373 "Set the current default output port to PORT.")
1bbd0b84 374#define FUNC_NAME s_scm_set_current_output_port
0f2d19dd
JB
375{
376 SCM ooutp = scm_cur_outp;
78446828 377 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 378 SCM_VALIDATE_OPOUTPORT (1,port);
0f2d19dd
JB
379 scm_cur_outp = port;
380 return ooutp;
381}
1bbd0b84 382#undef FUNC_NAME
0f2d19dd
JB
383
384
3b3b36dd 385SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
1bbd0b84 386 (SCM port),
b450f070 387 "Set the current default error port to PORT.")
1bbd0b84 388#define FUNC_NAME s_scm_set_current_error_port
0f2d19dd
JB
389{
390 SCM oerrp = scm_cur_errp;
78446828 391 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 392 SCM_VALIDATE_OPOUTPORT (1,port);
0f2d19dd
JB
393 scm_cur_errp = port;
394 return oerrp;
395}
1bbd0b84 396#undef FUNC_NAME
0f2d19dd
JB
397
398\f
840ae05d 399/* The port table --- an array of pointers to ports. */
0f2d19dd 400
840ae05d 401scm_port **scm_port_table;
0f2d19dd
JB
402
403int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
404int scm_port_table_room = 20; /* Size of the array. */
405
ee149d03 406/* Add a port to the table. */
1cc91f1b 407
840ae05d 408scm_port *
a284e297 409scm_add_to_port_table (SCM port)
0f2d19dd 410{
840ae05d
JB
411 scm_port *entry;
412
0f2d19dd
JB
413 if (scm_port_table_size == scm_port_table_room)
414 {
ee149d03 415 void *newt = realloc ((char *) scm_port_table,
840ae05d 416 (scm_sizet) (sizeof (scm_port *)
ee149d03
JB
417 * scm_port_table_room * 2));
418 if (newt == NULL)
840ae05d
JB
419 scm_memory_error ("scm_add_to_port_table");
420 scm_port_table = (scm_port **) newt;
0f2d19dd
JB
421 scm_port_table_room *= 2;
422 }
840ae05d
JB
423 entry = (scm_port *) malloc (sizeof (scm_port));
424 if (entry == NULL)
425 scm_memory_error ("scm_add_to_port_table");
426
427 entry->port = port;
428 entry->entry = scm_port_table_size;
429 entry->revealed = 0;
430 entry->stream = 0;
431 entry->file_name = SCM_BOOL_F;
432 entry->line_number = 0;
433 entry->column_number = 0;
6c951427
GH
434 entry->putback_buf = 0;
435 entry->putback_buf_size = 0;
61e452ba 436 entry->rw_active = SCM_PORT_NEITHER;
0de97b83 437 entry->rw_random = 0;
840ae05d
JB
438
439 scm_port_table[scm_port_table_size] = entry;
440 scm_port_table_size++;
441
442 return entry;
0f2d19dd
JB
443}
444
6c951427 445/* Remove a port from the table and destroy it. */
1cc91f1b 446
0f2d19dd 447void
a284e297 448scm_remove_from_port_table (SCM port)
0f2d19dd 449{
840ae05d 450 scm_port *p = SCM_PTAB_ENTRY (port);
ee1e7e13 451 int i = p->entry;
6c951427 452
ee1e7e13
MD
453 if (i >= scm_port_table_size)
454 scm_wta (port, "Port not in table", "scm_remove_from_port_table");
6c951427
GH
455 if (p->putback_buf)
456 free (p->putback_buf);
840ae05d 457 free (p);
ee1e7e13
MD
458 /* Since we have just freed slot i we can shrink the table by moving
459 the last entry to that slot... */
460 if (i < scm_port_table_size - 1)
0f2d19dd 461 {
ee1e7e13
MD
462 scm_port_table[i] = scm_port_table[scm_port_table_size - 1];
463 scm_port_table[i]->entry = i;
0f2d19dd 464 }
0f2d19dd
JB
465 SCM_SETPTAB_ENTRY (port, 0);
466 scm_port_table_size--;
467}
468
fea6b4ea 469#ifdef GUILE_DEBUG
b450f070 470/* Functions for debugging. */
1cc91f1b 471
3b3b36dd 472SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
b450f070
GB
473 (),
474 "Returns the number of ports in the port table.\n"
475 "`pt-size' is only included in GUILE_DEBUG builds.")
1bbd0b84 476#define FUNC_NAME s_scm_pt_size
0f2d19dd
JB
477{
478 return SCM_MAKINUM (scm_port_table_size);
479}
1bbd0b84 480#undef FUNC_NAME
0f2d19dd 481
3b3b36dd 482SCM_DEFINE (scm_pt_member, "pt-member", 1, 0, 0,
b450f070
GB
483 (SCM index),
484 "Returns the port at INDEX in the port table.\n"
485 "`pt-member' is only included in GUILE_DEBUG builds.")
1bbd0b84 486#define FUNC_NAME s_scm_pt_member
0f2d19dd
JB
487{
488 int i;
b450f070 489 SCM_VALIDATE_INUM_COPY (1,index,i);
0f2d19dd
JB
490 if (i < 0 || i >= scm_port_table_size)
491 return SCM_BOOL_F;
492 else
493 return scm_port_table[i]->port;
494}
1bbd0b84 495#undef FUNC_NAME
0f2d19dd
JB
496#endif
497
70df8af6
GH
498void
499scm_port_non_buffer (scm_port *pt)
500{
501 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
502 pt->write_buf = pt->write_pos = &pt->shortbuf;
503 pt->read_buf_size = pt->write_buf_size = 1;
504 pt->write_end = pt->write_buf + pt->write_buf_size;
505}
0f2d19dd 506
d68fee48
JB
507\f
508/* Revealed counts --- an oddity inherited from SCSH. */
509
8b13c6b3
GH
510/* Find a port in the table and return its revealed count.
511 Also used by the garbage collector.
0f2d19dd 512 */
1cc91f1b 513
0f2d19dd 514int
a284e297 515scm_revealed_count (SCM port)
0f2d19dd
JB
516{
517 return SCM_REVEALED(port);
518}
519
520
521
522/* Return the revealed count for a port. */
523
3b3b36dd 524SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
1bbd0b84 525 (SCM port),
b380b885 526 "Returns the revealed count for @var{port}.")
1bbd0b84 527#define FUNC_NAME s_scm_port_revealed
0f2d19dd 528{
78446828 529 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 530 SCM_VALIDATE_PORT (1,port);
8b13c6b3 531 return SCM_MAKINUM (scm_revealed_count (port));
0f2d19dd 532}
1bbd0b84 533#undef FUNC_NAME
0f2d19dd
JB
534
535/* Set the revealed count for a port. */
3b3b36dd 536SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
1bbd0b84 537 (SCM port, SCM rcount),
b450f070 538 "Sets the revealed count for a port to a given value.\n"
b380b885 539 "The return value is unspecified.")
1bbd0b84 540#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 541{
78446828 542 port = SCM_COERCE_OUTPORT (port);
3b3b36dd
GB
543 SCM_VALIDATE_PORT (1,port);
544 SCM_VALIDATE_INUM (2,rcount);
0f2d19dd 545 SCM_REVEALED (port) = SCM_INUM (rcount);
8b13c6b3 546 return SCM_UNSPECIFIED;
0f2d19dd 547}
1bbd0b84 548#undef FUNC_NAME
0f2d19dd 549
d68fee48
JB
550
551\f
552/* Retrieving a port's mode. */
553
eadd48de
GH
554/* Return the flags that characterize a port based on the mode
555 * string used to open a file for that port.
556 *
557 * See PORT FLAGS in scm.h
558 */
559
560long
a284e297 561scm_mode_bits (char *modes)
eadd48de
GH
562{
563 return (SCM_OPN
564 | (strchr (modes, 'r') || strchr (modes, '+') ? SCM_RDNG : 0)
565 | ( strchr (modes, 'w')
566 || strchr (modes, 'a')
567 || strchr (modes, '+') ? SCM_WRTNG : 0)
ee149d03
JB
568 | (strchr (modes, '0') ? SCM_BUF0 : 0)
569 | (strchr (modes, 'l') ? SCM_BUFLINE : 0));
eadd48de
GH
570}
571
572
573/* Return the mode flags from an open port.
574 * Some modes such as "append" are only used when opening
575 * a file and are not returned here. */
576
3b3b36dd 577SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
1bbd0b84 578 (SCM port),
b380b885
MD
579 "Returns the port modes associated with the open port @var{port}. These\n"
580 "will not necessarily be identical to the modes used when the port was\n"
581 "opened, since modes such as \"append\" which are used only during\n"
582 "port creation are not retained.")
1bbd0b84 583#define FUNC_NAME s_scm_port_mode
eadd48de
GH
584{
585 char modes[3];
586 modes[0] = '\0';
78446828
MV
587
588 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 589 SCM_VALIDATE_OPPORT (1,port);
f9a64404
DH
590 if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
591 if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de
GH
592 strcpy (modes, "r+");
593 else
594 strcpy (modes, "r");
595 }
f9a64404 596 else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
eadd48de 597 strcpy (modes, "w");
f9a64404 598 if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
eadd48de
GH
599 strcat (modes, "0");
600 return scm_makfromstr (modes, strlen (modes), 0);
601}
1bbd0b84 602#undef FUNC_NAME
eadd48de
GH
603
604
d68fee48
JB
605\f
606/* Closing ports. */
607
0f2d19dd
JB
608/* scm_close_port
609 * Call the close operation on a port object.
eadd48de 610 * see also scm_close.
0f2d19dd 611 */
3b3b36dd 612SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
1bbd0b84 613 (SCM port),
b380b885
MD
614 "Close the specified port object. Returns @code{#t} if it successfully\n"
615 "closes a port or @code{#f} if it was already\n"
616 "closed. An exception may be raised if an error occurs, for example\n"
617 "when flushing buffered output.\n"
618 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
619 "which can close file descriptors.")
1bbd0b84 620#define FUNC_NAME s_scm_close_port
0f2d19dd
JB
621{
622 scm_sizet i;
eadd48de
GH
623 int rv;
624
78446828
MV
625 port = SCM_COERCE_OUTPORT (port);
626
7a754ca6 627 SCM_VALIDATE_PORT (1, port);
0f2d19dd 628 if (SCM_CLOSEDP (port))
eadd48de 629 return SCM_BOOL_F;
0f2d19dd 630 i = SCM_PTOBNUM (port);
affc96b5
GH
631 if (scm_ptobs[i].close)
632 rv = (scm_ptobs[i].close) (port);
eadd48de
GH
633 else
634 rv = 0;
0f2d19dd 635 scm_remove_from_port_table (port);
898a256f 636 SCM_SETAND_CAR (port, ~SCM_OPN);
7a754ca6
MD
637 return SCM_NEGATE_BOOL (rv < 0);
638}
639#undef FUNC_NAME
640
641SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
642 (SCM port),
643 "Close the specified input port object. The routine has no effect if\n"
644 "the file has already been closed. An exception may be raised if an\n"
645 "error occurs. The value returned is unspecified.\n\n"
646 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
647 "which can close file descriptors.")
648#define FUNC_NAME s_scm_close_input_port
649{
650 SCM_VALIDATE_INPUT_PORT (1, port);
651 scm_close_port (port);
652 return SCM_UNSPECIFIED;
653}
654#undef FUNC_NAME
655
656SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
657 (SCM port),
658 "Close the specified output port object. The routine has no effect if\n"
659 "the file has already been closed. An exception may be raised if an\n"
660 "error occurs. The value returned is unspecified.\n\n"
661 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
662 "which can close file descriptors.")
663#define FUNC_NAME s_scm_close_output_port
664{
665 port = SCM_COERCE_OUTPORT (port);
666 SCM_VALIDATE_OUTPUT_PORT (1, port);
667 scm_close_port (port);
668 return SCM_UNSPECIFIED;
0f2d19dd 669}
1bbd0b84 670#undef FUNC_NAME
0f2d19dd 671
c2ca4493
GH
672SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
673 (SCM proc),
674 "Apply @var{proc} to each port in the Guile port table\n"
675 "in turn. The return value is unspecified.")
676#define FUNC_NAME s_scm_port_for_each
677{
678 int i;
679 SCM_VALIDATE_PROC (1, proc);
680
681 /* when pre-emptive multithreading is supported, access to the port
682 table will need to be controlled by a mutex. */
683 SCM_DEFER_INTS;
684 for (i = 0; i < scm_port_table_size; i++)
685 {
686 scm_apply (proc, scm_cons (scm_port_table[i]->port, SCM_EOL), SCM_EOL);
687 }
688 return SCM_UNSPECIFIED;
689}
690#undef FUNC_NAME
691
b875c468
GH
692#if (SCM_DEBUG_DEPRECATED == 0)
693
3b3b36dd 694SCM_DEFINE (scm_close_all_ports_except, "close-all-ports-except", 0, 0, 1,
1bbd0b84 695 (SCM ports),
b875c468 696 "[DEPRECATED] Close all open file ports used by the interpreter\n"
b380b885 697 "except for those supplied as arguments. This procedure\n"
b875c468
GH
698 "was intended to be used before an exec call to close file descriptors\n"
699 "which are not needed in the new process. However it has the\n"
700 "undesirable side-effect of flushing buffes, so it's deprecated.\n"
701 "Use port-for-each instead.")
1bbd0b84 702#define FUNC_NAME s_scm_close_all_ports_except
0f2d19dd
JB
703{
704 int i = 0;
af45e3b0 705 SCM_VALIDATE_REST_ARGUMENT (ports);
0f2d19dd
JB
706 while (i < scm_port_table_size)
707 {
708 SCM thisport = scm_port_table[i]->port;
709 int found = 0;
710 SCM ports_ptr = ports;
711
712 while (SCM_NNULLP (ports_ptr))
713 {
78446828 714 SCM port = SCM_COERCE_OUTPORT (SCM_CAR (ports_ptr));
0f2d19dd 715 if (i == 0)
3b3b36dd 716 SCM_VALIDATE_OPPORT (SCM_ARG1,port);
54778cd3 717 if (SCM_EQ_P (port, thisport))
0f2d19dd
JB
718 found = 1;
719 ports_ptr = SCM_CDR (ports_ptr);
720 }
721 if (found)
722 i++;
723 else
724 /* i is not to be incremented here. */
725 scm_close_port (thisport);
726 }
0f2d19dd
JB
727 return SCM_UNSPECIFIED;
728}
1bbd0b84 729#undef FUNC_NAME
0f2d19dd 730
b875c468 731#endif
d68fee48
JB
732
733\f
734/* Utter miscellany. Gosh, we should clean this up some time. */
735
3b3b36dd 736SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
1bbd0b84 737 (SCM x),
bfc46627
GB
738 "Returns @code{#t} if @var{x} is an input port, otherwise returns\n"
739 "@code{#f}. Any object satisfying this predicate also satisfies\n"
740 "@code{port?}.")
1bbd0b84 741#define FUNC_NAME s_scm_input_port_p
0f2d19dd
JB
742{
743 if (SCM_IMP (x))
4a94d8ca 744 return SCM_BOOL_F;
f5f2dcff 745 return SCM_BOOL(SCM_INPUT_PORT_P (x));
0f2d19dd 746}
1bbd0b84 747#undef FUNC_NAME
0f2d19dd 748
3b3b36dd 749SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
1bbd0b84 750 (SCM x),
bfc46627
GB
751 "Returns @code{#t} if @var{x} is an output port, otherwise returns\n"
752 "@code{#f}. Any object satisfying this predicate also satisfies\n"
753 "@code{port?}.")
1bbd0b84 754#define FUNC_NAME s_scm_output_port_p
0f2d19dd
JB
755{
756 if (SCM_IMP (x))
4a94d8ca
MD
757 return SCM_BOOL_F;
758 if (SCM_PORT_WITH_PS_P (x))
759 x = SCM_PORT_WITH_PS_PORT (x);
f5f2dcff 760 return SCM_BOOL(SCM_OUTPUT_PORT_P (x));
0f2d19dd 761}
1bbd0b84 762#undef FUNC_NAME
0f2d19dd 763
eb5c0a2a
GH
764SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
765 (SCM x),
766 "Returns a boolean indicating whether @var{x} is a port.\n"
767 "Equivalent to @code{(or (input-port? X) (output-port? X))}.")
768#define FUNC_NAME s_scm_port_p
769{
770 return SCM_BOOL (SCM_PORTP (x));
771}
772#undef FUNC_NAME
773
3b3b36dd 774SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
1bbd0b84 775 (SCM port),
b380b885 776 "Returns @code{#t} if @var{port} is closed or @code{#f} if it is open.")
1bbd0b84 777#define FUNC_NAME s_scm_port_closed_p
60d0643d 778{
c1bfcf60 779 SCM_VALIDATE_PORT (1,port);
1bbd0b84 780 return SCM_NEGATE_BOOL(SCM_OPPORTP (port));
60d0643d 781}
1bbd0b84 782#undef FUNC_NAME
0f2d19dd 783
3b3b36dd 784SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
1bbd0b84 785 (SCM x),
bfc46627
GB
786 "Returns @code{#t} if @var{x} is an end-of-file object; otherwise\n"
787 "returns @code{#f}.")
1bbd0b84 788#define FUNC_NAME s_scm_eof_object_p
0f2d19dd 789{
1bbd0b84 790 return SCM_BOOL(SCM_EOF_OBJECT_P (x));
0f2d19dd 791}
1bbd0b84 792#undef FUNC_NAME
0f2d19dd 793
3b3b36dd 794SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
1bbd0b84 795 (SCM port),
b380b885
MD
796 "Flush the specified output port, or the current output port if @var{port}\n"
797 "is omitted. The current output buffer contents are passed to the \n"
798 "underlying port implementation (e.g., in the case of fports, the\n"
799 "data will be written to the file and the output buffer will be cleared.)\n"
800 "It has no effect on an unbuffered port.\n\n"
801 "The return value is unspecified.")
1bbd0b84 802#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
803{
804 if (SCM_UNBNDP (port))
3e877d15 805 port = scm_cur_outp;
0f2d19dd 806 else
78446828
MV
807 {
808 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 809 SCM_VALIDATE_OPOUTPORT (1,port);
78446828 810 }
affc96b5 811 scm_flush (port);
ee149d03 812 return SCM_UNSPECIFIED;
0f2d19dd 813}
1bbd0b84 814#undef FUNC_NAME
0f2d19dd 815
a1ec6916 816SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
1bbd0b84 817 (),
b380b885
MD
818 "Equivalent to calling @code{force-output} on\n"
819 "all open output ports. The return value is unspecified.")
1bbd0b84 820#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c
GH
821{
822 int i;
823
824 for (i = 0; i < scm_port_table_size; i++)
825 {
ee149d03 826 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
affc96b5 827 scm_flush (scm_port_table[i]->port);
89ea5b7c
GH
828 }
829 return SCM_UNSPECIFIED;
830}
1bbd0b84 831#undef FUNC_NAME
0f2d19dd 832
3b3b36dd 833SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1bbd0b84 834 (SCM port),
bfc46627
GB
835 "Returns the next character available from @var{port}, updating\n"
836 "@var{port} to point to the following character. If no more\n"
837 "characters are available, an end-of-file object is returned.")
1bbd0b84 838#define FUNC_NAME s_scm_read_char
0f2d19dd
JB
839{
840 int c;
841 if (SCM_UNBNDP (port))
334341aa 842 port = scm_cur_inp;
3b3b36dd 843 SCM_VALIDATE_OPINPORT (1,port);
b7f3516f 844 c = scm_getc (port);
0f2d19dd
JB
845 if (EOF == c)
846 return SCM_EOF_VAL;
7866a09b 847 return SCM_MAKE_CHAR (c);
0f2d19dd 848}
1bbd0b84 849#undef FUNC_NAME
0f2d19dd 850
5c070ca7 851/* this should only be called when the read buffer is empty. it
affc96b5 852 tries to refill the read buffer. it returns the first char from
5c070ca7 853 the port, which is either EOF or *(pt->read_pos). */
6c951427 854int
affc96b5 855scm_fill_input (SCM port)
6c951427 856{
283a1a0e
GH
857 scm_port *pt = SCM_PTAB_ENTRY (port);
858
6c951427
GH
859 if (pt->read_buf == pt->putback_buf)
860 {
861 /* finished reading put-back chars. */
862 pt->read_buf = pt->saved_read_buf;
863 pt->read_pos = pt->saved_read_pos;
864 pt->read_end = pt->saved_read_end;
865 pt->read_buf_size = pt->saved_read_buf_size;
866 if (pt->read_pos < pt->read_end)
5c070ca7 867 return *(pt->read_pos);
6c951427 868 }
affc96b5 869 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
870}
871
ee149d03 872int
a284e297 873scm_getc (SCM port)
0f2d19dd
JB
874{
875 int c;
840ae05d 876 scm_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 877
840ae05d
JB
878 if (pt->rw_active == SCM_PORT_WRITE)
879 {
affc96b5
GH
880 /* may be marginally faster than calling scm_flush. */
881 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
840ae05d 882 }
6c951427 883
5c070ca7
GH
884 if (pt->rw_random)
885 pt->rw_active = SCM_PORT_READ;
886
887 if (pt->read_pos >= pt->read_end)
ee149d03 888 {
affc96b5 889 if (scm_fill_input (port) == EOF)
5c070ca7 890 return EOF;
ee149d03
JB
891 }
892
5c070ca7 893 c = *(pt->read_pos++);
840ae05d 894
ee149d03
JB
895 if (c == '\n')
896 {
897 SCM_INCLINE (port);
898 }
899 else if (c == '\t')
900 {
901 SCM_TABCOL (port);
902 }
903 else
904 {
905 SCM_INCCOL (port);
906 }
907
908 return c;
0f2d19dd
JB
909}
910
ee149d03 911void
a284e297 912scm_putc (char c, SCM port)
ee149d03 913{
265e6a4d 914 scm_lfwrite (&c, 1, port);
ee149d03 915}
3cb988bd 916
ee149d03 917void
70d63753 918scm_puts (const char *s, SCM port)
3cb988bd 919{
265e6a4d 920 scm_lfwrite (s, strlen (s), port);
ee149d03 921}
3cb988bd 922
ee149d03 923void
70d63753 924scm_lfwrite (const char *ptr, scm_sizet size, SCM port)
ee149d03 925{
840ae05d 926 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 927 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 928
840ae05d 929 if (pt->rw_active == SCM_PORT_READ)
affc96b5 930 scm_end_input (port);
283a1a0e 931
31703ab8 932 ptob->write (port, ptr, size);
840ae05d
JB
933
934 if (pt->rw_random)
935 pt->rw_active = SCM_PORT_WRITE;
ee149d03 936}
3cb988bd 937
3cb988bd 938
ee149d03 939void
a284e297 940scm_flush (SCM port)
ee149d03
JB
941{
942 scm_sizet i = SCM_PTOBNUM (port);
affc96b5 943 (scm_ptobs[i].flush) (port);
ee149d03
JB
944}
945
283a1a0e 946void
a284e297 947scm_end_input (SCM port)
283a1a0e
GH
948{
949 int offset;
950 scm_port *pt = SCM_PTAB_ENTRY (port);
951
952 if (pt->read_buf == pt->putback_buf)
953 {
954 offset = pt->read_end - pt->read_pos;
955 pt->read_buf = pt->saved_read_buf;
956 pt->read_pos = pt->saved_read_pos;
957 pt->read_end = pt->saved_read_end;
958 pt->read_buf_size = pt->saved_read_buf_size;
959 }
960 else
961 offset = 0;
962
affc96b5 963 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
964}
965
ee149d03
JB
966\f
967
968
969void
a284e297 970scm_ungetc (int c, SCM port)
ee149d03 971{
840ae05d
JB
972 scm_port *pt = SCM_PTAB_ENTRY (port);
973
6c951427
GH
974 if (pt->read_buf == pt->putback_buf)
975 /* already using the put-back buffer. */
976 {
977 /* enlarge putback_buf if necessary. */
978 if (pt->read_end == pt->read_buf + pt->read_buf_size
979 && pt->read_buf == pt->read_pos)
980 {
981 int new_size = pt->read_buf_size * 2;
982 unsigned char *tmp =
983 (unsigned char *) realloc (pt->putback_buf, new_size);
984
985 if (tmp == NULL)
986 scm_memory_error ("scm_ungetc");
987 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
988 pt->read_end = pt->read_buf + pt->read_buf_size;
989 pt->read_buf_size = pt->putback_buf_size = new_size;
990 }
991
992 /* shift any existing bytes to buffer + 1. */
993 if (pt->read_pos == pt->read_end)
994 pt->read_end = pt->read_buf + 1;
995 else if (pt->read_pos != pt->read_buf + 1)
996 {
997 int count = pt->read_end - pt->read_pos;
998
999 memmove (pt->read_buf + 1, pt->read_pos, count);
1000 pt->read_end = pt->read_buf + 1 + count;
1001 }
1002
1003 pt->read_pos = pt->read_buf;
1004 }
1005 else
1006 /* switch to the put-back buffer. */
1007 {
1008 if (pt->putback_buf == NULL)
1009 {
c357d546
MD
1010 pt->putback_buf
1011 = (unsigned char *) malloc (SCM_INITIAL_PUTBACK_BUF_SIZE);
6c951427
GH
1012 if (pt->putback_buf == NULL)
1013 scm_memory_error ("scm_ungetc");
1014 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
1015 }
1016
1017 pt->saved_read_buf = pt->read_buf;
1018 pt->saved_read_pos = pt->read_pos;
1019 pt->saved_read_end = pt->read_end;
1020 pt->saved_read_buf_size = pt->read_buf_size;
1021
1022 pt->read_pos = pt->read_buf = pt->putback_buf;
1023 pt->read_end = pt->read_buf + 1;
1024 pt->read_buf_size = pt->putback_buf_size;
1025 }
1026
1027 *pt->read_buf = c;
ee149d03 1028
840ae05d
JB
1029 if (pt->rw_random)
1030 pt->rw_active = SCM_PORT_READ;
1031
ee149d03
JB
1032 if (c == '\n')
1033 {
1034 /* What should col be in this case?
1035 * We'll leave it at -1.
1036 */
1037 SCM_LINUM (port) -= 1;
1038 }
1039 else
1040 SCM_COL(port) -= 1;
1041}
1042
1043
1044void
70d63753 1045scm_ungets (const char *s, int n, SCM port)
ee149d03
JB
1046{
1047 /* This is simple minded and inefficient, but unreading strings is
1048 * probably not a common operation, and remember that line and
1049 * column numbers have to be handled...
1050 *
1051 * Please feel free to write an optimized version!
1052 */
1053 while (n--)
1054 scm_ungetc (s[n], port);
1055}
1056
1057
3b3b36dd 1058SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1bbd0b84 1059 (SCM port),
bfc46627
GB
1060 "Returns the next character available from @var{port},\n"
1061 "@emph{without} updating @var{port} to point to the following\n"
1062 "character. If no more characters are available, an end-of-file object\n"
1063 "is returned.@footnote{The value returned by a call to @code{peek-char}\n"
1064 "is the same as the value that would have been returned by a call to\n"
1065 "@code{read-char} on the same port. The only difference is that the very\n"
1066 "next call to @code{read-char} or @code{peek-char} on that\n"
1067 "@var{port} will return the value returned by the preceding call to\n"
1068 "@code{peek-char}. In particular, a call to @code{peek-char} on an\n"
1069 "interactive port will hang waiting for input whenever a call to\n"
1070 "@code{read-char} would have hung.}")
1bbd0b84 1071#define FUNC_NAME s_scm_peek_char
ee149d03
JB
1072{
1073 int c;
1074 if (SCM_UNBNDP (port))
1075 port = scm_cur_inp;
1076 else
3b3b36dd 1077 SCM_VALIDATE_OPINPORT (1,port);
ee149d03
JB
1078 c = scm_getc (port);
1079 if (EOF == c)
1080 return SCM_EOF_VAL;
1081 scm_ungetc (c, port);
7866a09b 1082 return SCM_MAKE_CHAR (c);
3cb988bd 1083}
1bbd0b84 1084#undef FUNC_NAME
3cb988bd 1085
a1ec6916 1086SCM_DEFINE (scm_unread_char, "unread-char", 2, 0, 0,
1bbd0b84 1087 (SCM cobj, SCM port),
b380b885
MD
1088 "Place @var{char} in @var{port} so that it will be read by the\n"
1089 "next read operation. If called multiple times, the unread characters\n"
1090 "will be read again in last-in first-out order. If @var{port} is\n"
1091 "not supplied, the current input port is used.")
1bbd0b84 1092#define FUNC_NAME s_scm_unread_char
0f2d19dd
JB
1093{
1094 int c;
1095
7866a09b 1096 SCM_VALIDATE_CHAR (1,cobj);
0f2d19dd
JB
1097 if (SCM_UNBNDP (port))
1098 port = scm_cur_inp;
1099 else
3b3b36dd 1100 SCM_VALIDATE_OPINPORT (2,port);
0f2d19dd 1101
7866a09b 1102 c = SCM_CHAR (cobj);
0f2d19dd 1103
b7f3516f 1104 scm_ungetc (c, port);
0f2d19dd
JB
1105 return cobj;
1106}
1bbd0b84 1107#undef FUNC_NAME
0f2d19dd 1108
a1ec6916 1109SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1bbd0b84 1110 (SCM str, SCM port),
b380b885
MD
1111 "Place the string @var{str} in @var{port} so that its characters will be\n"
1112 "read in subsequent read operations. If called multiple times, the\n"
1113 "unread characters will be read again in last-in first-out order. If\n"
1114 "@var{port} is not supplied, the current-input-port is used.")
1bbd0b84 1115#define FUNC_NAME s_scm_unread_string
ee1e7e13 1116{
3b3b36dd 1117 SCM_VALIDATE_STRING (1,str);
ee1e7e13
MD
1118 if (SCM_UNBNDP (port))
1119 port = scm_cur_inp;
1120 else
3b3b36dd 1121 SCM_VALIDATE_OPINPORT (2,port);
ee1e7e13 1122
34f0f2b8 1123 scm_ungets (SCM_STRING_CHARS (str), SCM_STRING_LENGTH (str), port);
ee1e7e13
MD
1124
1125 return str;
1126}
1bbd0b84 1127#undef FUNC_NAME
ee1e7e13 1128
a1ec6916 1129SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1bbd0b84 1130 (SCM object, SCM offset, SCM whence),
b380b885
MD
1131 "Sets the current position of @var{fd/port} to the integer @var{offset},\n"
1132 "which is interpreted according to the value of @var{whence}.\n\n"
1133 "One of the following variables should be supplied\n"
1134 "for @var{whence}:\n"
1135 "@defvar SEEK_SET\n"
1136 "Seek from the beginning of the file.\n"
1137 "@end defvar\n"
1138 "@defvar SEEK_CUR\n"
1139 "Seek from the current position.\n"
1140 "@end defvar\n"
1141 "@defvar SEEK_END\n"
1142 "Seek from the end of the file.\n"
1143 "@end defvar\n\n"
1144 "If @var{fd/port} is a file descriptor, the underlying system call is\n"
1145 "@code{lseek}. @var{port} may be a string port.\n\n"
1146 "The value returned is the new position in the file. This means that\n"
1147 "the current position of a port can be obtained using:\n"
1148 "@smalllisp\n"
1149 "(seek port 0 SEEK_CUR)\n"
1150 "@end smalllisp")
1bbd0b84 1151#define FUNC_NAME s_scm_seek
840ae05d
JB
1152{
1153 off_t off;
1154 off_t rv;
1155 int how;
1156
1157 object = SCM_COERCE_OUTPORT (object);
1158
1bbd0b84 1159 off = SCM_NUM2LONG (2,offset);
3b3b36dd 1160 SCM_VALIDATE_INUM_COPY (3,whence,how);
840ae05d 1161 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1bbd0b84 1162 SCM_OUT_OF_RANGE (3, whence);
0c95b57d 1163 if (SCM_OPPORTP (object))
840ae05d 1164 {
f12733c9 1165 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
840ae05d
JB
1166
1167 if (!ptob->seek)
1bbd0b84
GB
1168 SCM_MISC_ERROR ("port is not seekable",
1169 scm_cons (object, SCM_EOL));
840ae05d 1170 else
7dcb364d 1171 rv = ptob->seek (object, off, how);
840ae05d
JB
1172 }
1173 else /* file descriptor?. */
1174 {
3b3b36dd 1175 SCM_VALIDATE_INUM (1,object);
840ae05d
JB
1176 rv = lseek (SCM_INUM (object), off, how);
1177 if (rv == -1)
1bbd0b84 1178 SCM_SYSERROR;
840ae05d
JB
1179 }
1180 return scm_long2num (rv);
1181}
1bbd0b84 1182#undef FUNC_NAME
840ae05d 1183
a1ec6916 1184SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1bbd0b84 1185 (SCM object, SCM length),
b380b885
MD
1186 "Truncates the object referred to by @var{obj} to at most @var{size} bytes.\n"
1187 "@var{obj} can be a string containing a file name or an integer file\n"
1188 "descriptor or a port. @var{size} may be omitted if @var{obj} is not\n"
1189 "a file name, in which case the truncation occurs at the current port.\n"
1190 "position.\n\n"
1191 "The return value is unspecified.")
1bbd0b84 1192#define FUNC_NAME s_scm_truncate_file
840ae05d 1193{
69bc9ff3
GH
1194 int rv;
1195 off_t c_length;
1196
1197 /* object can be a port, fdes or filename. */
840ae05d 1198
840ae05d
JB
1199 if (SCM_UNBNDP (length))
1200 {
69bc9ff3 1201 /* must supply length if object is a filename. */
a6d9e5ab 1202 if (SCM_STRINGP (object))
c1bfcf60 1203 SCM_MISC_ERROR("must supply length if OBJECT is a filename",SCM_EOL);
69bc9ff3 1204
c94577b4 1205 length = scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
840ae05d 1206 }
1bbd0b84 1207 c_length = SCM_NUM2LONG (2,length);
69bc9ff3 1208 if (c_length < 0)
1bbd0b84 1209 SCM_MISC_ERROR ("negative offset", SCM_EOL);
3fe6190f 1210
69bc9ff3
GH
1211 object = SCM_COERCE_OUTPORT (object);
1212 if (SCM_INUMP (object))
1213 {
1214 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1215 }
0c95b57d 1216 else if (SCM_OPOUTPORTP (object))
69bc9ff3
GH
1217 {
1218 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1219 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1220
affc96b5 1221 if (!ptob->truncate)
1bbd0b84 1222 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1223 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1224 scm_end_input (object);
69bc9ff3 1225 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1226 ptob->flush (object);
69bc9ff3 1227
affc96b5 1228 ptob->truncate (object, c_length);
69bc9ff3
GH
1229 rv = 0;
1230 }
1231 else
1232 {
a6d9e5ab
DH
1233 SCM_VALIDATE_STRING (1, object);
1234 SCM_STRING_COERCE_0TERMINATION_X (object);
1235 SCM_SYSCALL (rv = truncate (SCM_STRING_CHARS (object), c_length));
69bc9ff3
GH
1236 }
1237 if (rv == -1)
1bbd0b84 1238 SCM_SYSERROR;
840ae05d
JB
1239 return SCM_UNSPECIFIED;
1240}
1bbd0b84 1241#undef FUNC_NAME
840ae05d 1242
a1ec6916 1243SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1bbd0b84 1244 (SCM port),
b450f070 1245 "Return the current line number for PORT.")
1bbd0b84 1246#define FUNC_NAME s_scm_port_line
0f2d19dd 1247{
78446828 1248 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1249 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1250 return SCM_MAKINUM (SCM_LINUM (port));
0f2d19dd 1251}
1bbd0b84 1252#undef FUNC_NAME
0f2d19dd 1253
a1ec6916 1254SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1bbd0b84 1255 (SCM port, SCM line),
b450f070 1256 "Set the current line number for PORT to LINE.")
1bbd0b84 1257#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1258{
360fc44c 1259 port = SCM_COERCE_OUTPORT (port);
3b3b36dd
GB
1260 SCM_VALIDATE_OPENPORT (1,port);
1261 SCM_VALIDATE_INUM (2,line);
564478fd
GB
1262 SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1263 return SCM_UNSPECIFIED;
d043d8c2 1264}
1bbd0b84 1265#undef FUNC_NAME
d043d8c2 1266
a1ec6916 1267SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1bbd0b84 1268 (SCM port),
b380b885
MD
1269 "@deffnx primitive port-line [input-port]\n"
1270 "Return the current column number or line number of @var{input-port},\n"
1271 "using the current input port if none is specified. If the number is\n"
1272 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1273 "- i.e. the first character of the first line is line 0, column 0.\n"
1274 "(However, when you display a file position, for example in an error\n"
1275 "message, we recommand you add 1 to get 1-origin integers. This is\n"
1276 "because lines and column numbers traditionally start with 1, and that is\n"
1277 "what non-programmers will find most natural.)")
1bbd0b84 1278#define FUNC_NAME s_scm_port_column
0f2d19dd 1279{
78446828 1280 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1281 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1282 return SCM_MAKINUM (SCM_COL (port));
0f2d19dd 1283}
1bbd0b84 1284#undef FUNC_NAME
0f2d19dd 1285
a1ec6916 1286SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1bbd0b84 1287 (SCM port, SCM column),
92ccc1f1
NJ
1288 "@deffnx primitive set-port-line! port line\n"
1289 "Set the current column or line number of @var{port}, using the\n"
b380b885 1290 "current input port if none is specified.")
1bbd0b84 1291#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1292{
360fc44c 1293 port = SCM_COERCE_OUTPORT (port);
3b3b36dd
GB
1294 SCM_VALIDATE_OPENPORT (1,port);
1295 SCM_VALIDATE_INUM (2,column);
564478fd
GB
1296 SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1297 return SCM_UNSPECIFIED;
d043d8c2 1298}
1bbd0b84 1299#undef FUNC_NAME
d043d8c2 1300
a1ec6916 1301SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1bbd0b84 1302 (SCM port),
b380b885 1303 "Return the filename associated with @var{port}. This function returns\n"
2a2a730b 1304 "the strings \"standard input\", \"standard output\" and \"standard error\"\n"
a3c8b9fc 1305 "when called on the current input, output and error ports respectively.")
1bbd0b84 1306#define FUNC_NAME s_scm_port_filename
0f2d19dd 1307{
78446828 1308 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1309 SCM_VALIDATE_OPENPORT (1,port);
b24b5e13 1310 return SCM_FILENAME (port);
0f2d19dd 1311}
1bbd0b84 1312#undef FUNC_NAME
0f2d19dd 1313
a1ec6916 1314SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1bbd0b84 1315 (SCM port, SCM filename),
b380b885
MD
1316 "Change the filename associated with @var{port}, using the current input\n"
1317 "port if none is specified. Note that this does not change the port's\n"
1318 "source of data, but only the value that is returned by\n"
1319 "@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1320#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1321{
360fc44c 1322 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1323 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1324 /* We allow the user to set the filename to whatever he likes. */
b24b5e13
DH
1325 SCM_SET_FILENAME (port, filename);
1326 return SCM_UNSPECIFIED;
d14af9f2 1327}
1bbd0b84 1328#undef FUNC_NAME
d14af9f2 1329
0f2d19dd
JB
1330#ifndef ttyname
1331extern char * ttyname();
1332#endif
1333
f12733c9
MD
1334void
1335scm_print_port_mode (SCM exp, SCM port)
1336{
1337 scm_puts (SCM_CLOSEDP (exp)
1338 ? "closed: "
f9a64404
DH
1339 : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
1340 ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1341 ? "input-output: "
1342 : "input: ")
f9a64404 1343 : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
f12733c9
MD
1344 ? "output: "
1345 : "bogus: ")),
1346 port);
1347}
1cc91f1b 1348
f12733c9
MD
1349int
1350scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 1351{
f12733c9
MD
1352 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1353 if (!type)
1354 type = "port";
b7f3516f 1355 scm_puts ("#<", port);
f12733c9 1356 scm_print_port_mode (exp, port);
b7f3516f
TT
1357 scm_puts (type, port);
1358 scm_putc (' ', port);
12a8b769 1359 scm_intprint (SCM_CELL_WORD_1 (exp), 16, port);
b7f3516f 1360 scm_putc ('>', port);
f12733c9 1361 return 1;
0f2d19dd
JB
1362}
1363
f12733c9
MD
1364extern void scm_make_fptob ();
1365extern void scm_make_stptob ();
1366extern void scm_make_sfptob ();
1cc91f1b 1367
0f2d19dd
JB
1368void
1369scm_ports_prehistory ()
0f2d19dd
JB
1370{
1371 scm_numptob = 0;
f12733c9 1372 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
0f2d19dd
JB
1373
1374 /* WARNING: These scm_newptob calls must be done in this order.
1375 * They must agree with the port declarations in tags.h.
1376 */
f12733c9
MD
1377 /* scm_tc16_fport = */ scm_make_fptob ();
1378 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1379 /* scm_tc16_strport = */ scm_make_stptob ();
1380 /* scm_tc16_sfport = */ scm_make_sfptob ();
0f2d19dd 1381}
0f2d19dd
JB
1382
1383\f
ee149d03 1384
d68fee48 1385/* Void ports. */
0f2d19dd 1386
f12733c9 1387long scm_tc16_void_port = 0;
0f2d19dd 1388
70df8af6 1389static int fill_input_void_port (SCM port)
283a1a0e 1390{
70df8af6 1391 return EOF;
283a1a0e
GH
1392}
1393
31703ab8 1394static void
8aa011a1 1395write_void_port (SCM port, const void *data, size_t size)
31703ab8
GH
1396{
1397}
1398
0f2d19dd 1399SCM
a284e297 1400scm_void_port (char *mode_str)
0f2d19dd
JB
1401{
1402 int mode_bits;
1403 SCM answer;
840ae05d 1404 scm_port * pt;
0f2d19dd
JB
1405
1406 SCM_NEWCELL (answer);
1407 SCM_DEFER_INTS;
1408 mode_bits = scm_mode_bits (mode_str);
1409 pt = scm_add_to_port_table (answer);
70df8af6 1410 scm_port_non_buffer (pt);
0f2d19dd 1411 SCM_SETPTAB_ENTRY (answer, pt);
ee149d03 1412 SCM_SETSTREAM (answer, 0);
54778cd3 1413 SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
0f2d19dd
JB
1414 SCM_ALLOW_INTS;
1415 return answer;
1416}
1417
a1ec6916 1418SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 1419 (SCM mode),
70df8af6
GH
1420 "Create and return a new void port. A void port acts like\n"
1421 "/dev/null. The @var{mode} argument\n"
1422 "specifies the input/output modes for this port: see the\n"
b380b885 1423 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1424#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1425{
a6d9e5ab
DH
1426 SCM_VALIDATE_STRING (1, mode);
1427 SCM_STRING_COERCE_0TERMINATION_X (mode);
1428 return scm_void_port (SCM_STRING_CHARS (mode));
0f2d19dd 1429}
1bbd0b84 1430#undef FUNC_NAME
0f2d19dd 1431
0f2d19dd 1432\f
89545eba 1433/* Initialization. */
1cc91f1b 1434
0f2d19dd
JB
1435void
1436scm_init_ports ()
0f2d19dd 1437{
840ae05d
JB
1438 /* lseek() symbols. */
1439 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1440 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1441 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1442
70df8af6
GH
1443 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
1444 write_void_port);
8dc9439f 1445#ifndef SCM_MAGIC_SNARFER
a0599745 1446#include "libguile/ports.x"
8dc9439f 1447#endif
0f2d19dd 1448}
89e00824
ML
1449
1450/*
1451 Local Variables:
1452 c-file-style: "gnu"
1453 End:
1454*/