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