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