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