* tests/r4rs.test (SECTION 3 4): Each element of type-matrix
[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. */
0f2d19dd 41\f
d68fee48
JB
42/* Headers. */
43
0f2d19dd
JB
44#include <stdio.h>
45#include "_scm.h"
f12733c9
MD
46#include "objects.h"
47#include "smob.h"
20e6290e 48#include "chars.h"
0f2d19dd 49
547e65b5 50#include "keywords.h"
20e6290e
JB
51
52#include "ports.h"
0f2d19dd
JB
53
54#ifdef HAVE_MALLOC_H
95b88819 55#include <malloc.h>
0f2d19dd
JB
56#endif
57
58#ifdef HAVE_UNISTD_H
59#include <unistd.h>
60#endif
61
95b88819
GH
62#ifdef HAVE_SYS_IOCTL_H
63#include <sys/ioctl.h>
64#endif
d68fee48 65
0f2d19dd 66\f
d68fee48 67/* The port kind table --- a dynamically resized array of port types. */
0f2d19dd
JB
68
69
70/* scm_ptobs scm_numptob
71 * implement a dynamicly resized array of ptob records.
72 * Indexes into this table are used when generating type
73 * tags for smobjects (if you know a tag you can get an index and conversely).
74 */
f12733c9 75scm_ptob_descriptor *scm_ptobs;
a1c95c45 76int scm_numptob;
0f2d19dd 77
ee149d03 78/* GC marker for a port with stream of SCM type. */
0f2d19dd
JB
79SCM
80scm_markstream (ptr)
81 SCM ptr;
0f2d19dd
JB
82{
83 int openp;
0f2d19dd 84 openp = SCM_CAR (ptr) & SCM_OPN;
0f2d19dd
JB
85 if (openp)
86 return SCM_STREAM (ptr);
87 else
88 return SCM_BOOL_F;
89}
90
f12733c9
MD
91/*
92 * This is how different port types currently use ptob fields.
93 *
94 * fports: free, flush, read_flush, close,
95 * fill_buffer, seek, truncate, input_waiting_p
96 *
97 * strports: mark, flush, read_flush,
98 * fill_buffer, seek, truncate
99 *
100 * softports: mark, flush, read_flush, close,
101 * fill_buffer
102 *
103 * voidports: (default values)
104 *
105 * We choose to use an interface similar to the smob interface with
106 * fill_buffer and write_flush as standard fields, passed to the port
107 * type constructor, and optional fields set by setters.
108 */
109
110static void flush_void_port (SCM port);
111static void read_flush_void_port (SCM port, int offset);
0f2d19dd 112
0f2d19dd 113long
f12733c9
MD
114scm_make_port_type (char *name,
115 int (*fill_buffer) (SCM port),
116 void (*write_flush) (SCM port))
0f2d19dd
JB
117{
118 char *tmp;
119 if (255 <= scm_numptob)
120 goto ptoberr;
f12733c9
MD
121 SCM_DEFER_INTS;
122 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
123 (1 + scm_numptob)
124 * sizeof (scm_ptob_descriptor)));
0f2d19dd
JB
125 if (tmp)
126 {
f12733c9
MD
127 scm_ptobs = (scm_ptob_descriptor *) tmp;
128 scm_ptobs[scm_numptob].name = name;
129 scm_ptobs[scm_numptob].mark = 0;
130 scm_ptobs[scm_numptob].free = scm_free0;
131 scm_ptobs[scm_numptob].print = scm_port_print;
132 scm_ptobs[scm_numptob].equalp = 0;
133 scm_ptobs[scm_numptob].fflush = (write_flush
134 ? write_flush
135 : flush_void_port);
136 scm_ptobs[scm_numptob].read_flush = read_flush_void_port;
137 scm_ptobs[scm_numptob].fclose = 0;
138 scm_ptobs[scm_numptob].fill_buffer = fill_buffer;
139 scm_ptobs[scm_numptob].seek = 0;
140 scm_ptobs[scm_numptob].ftruncate = 0;
141 scm_ptobs[scm_numptob].input_waiting_p = 0;
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
179void
6c747373 180scm_set_port_flush_input (long tc, void (*flush_input) (SCM port, int offset))
f12733c9
MD
181{
182 scm_ptobs[SCM_TC2PTOBNUM (tc)].read_flush = flush_input;
183}
184
185void
6c747373 186scm_set_port_close (long tc, int (*close) (SCM))
f12733c9
MD
187{
188 scm_ptobs[SCM_TC2PTOBNUM (tc)].fclose = close;
189}
190
191void
6c747373 192scm_set_port_seek (long tc, off_t (*seek) (SCM port,
f12733c9
MD
193 off_t OFFSET,
194 int WHENCE))
195{
196 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
197}
198
199void
6c747373 200scm_set_port_truncate (long tc, void (*truncate) (SCM port, off_t length))
f12733c9
MD
201{
202 scm_ptobs[SCM_TC2PTOBNUM (tc)].ftruncate = truncate;
203}
204
205void
6c747373 206scm_set_port_input_waiting_p (long tc, int (*waitingp) (SCM))
f12733c9
MD
207{
208 scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting_p = waitingp;
209}
210
0f2d19dd 211\f
0f2d19dd 212
44493941 213SCM_PROC(s_char_ready_p, "char-ready?", 0, 1, 0, scm_char_ready_p);
1cc91f1b 214
0f2d19dd
JB
215SCM
216scm_char_ready_p (port)
217 SCM port;
0f2d19dd 218{
6c951427
GH
219 scm_port *pt = SCM_PTAB_ENTRY (port);
220
0f2d19dd
JB
221 if (SCM_UNBNDP (port))
222 port = scm_cur_inp;
223 else
d68fee48
JB
224 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1,
225 s_char_ready_p);
226
6c951427
GH
227 /* if the current read buffer is filled, or the
228 last pushed-back char has been read and the saved buffer is
229 filled, result is true. */
230 if (pt->read_pos < pt->read_end
231 || (pt->read_buf == pt->putback_buf
232 && pt->saved_read_pos < pt->saved_read_end))
0f2d19dd 233 return SCM_BOOL_T;
ee149d03
JB
234 else
235 {
f12733c9 236 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
ee149d03 237
6c951427
GH
238 if (ptob->input_waiting_p)
239 return (ptob->input_waiting_p (port)) ? SCM_BOOL_T : SCM_BOOL_F;
ee149d03 240 else
6c951427 241 return SCM_BOOL_T;
ee149d03 242 }
0f2d19dd 243}
0f2d19dd 244
6c951427 245/* Clear a port's read buffers, returning the contents. */
ee149d03
JB
246SCM_PROC (s_drain_input, "drain-input", 1, 0, 0, scm_drain_input);
247SCM
248scm_drain_input (SCM port)
249{
840ae05d
JB
250 SCM result;
251 scm_port *pt = SCM_PTAB_ENTRY (port);
6c951427 252 int count;
840ae05d 253 char *dst;
ee149d03
JB
254
255 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1,
256 s_drain_input);
840ae05d 257
6c951427
GH
258 count = pt->read_end - pt->read_pos;
259 if (pt->read_buf == pt->putback_buf)
260 count += pt->saved_read_end - pt->saved_read_pos;
840ae05d 261
6c951427
GH
262 result = scm_makstr (count, 0);
263 dst = SCM_CHARS (result);
840ae05d
JB
264
265 while (pt->read_pos < pt->read_end)
6c951427
GH
266 *dst++ = *(pt->read_pos++);
267
268 if (pt->read_buf == pt->putback_buf)
840ae05d 269 {
6c951427
GH
270 while (pt->saved_read_pos < pt->saved_read_end)
271 *dst++ = *(pt->saved_read_pos++);
840ae05d 272 }
6c951427 273
840ae05d 274 return result;
ee149d03 275}
0f2d19dd
JB
276
277\f
d68fee48 278/* Standard ports --- current input, output, error, and more(!). */
0f2d19dd 279
0f2d19dd 280SCM_PROC(s_current_input_port, "current-input-port", 0, 0, 0, scm_current_input_port);
1cc91f1b 281
0f2d19dd
JB
282SCM
283scm_current_input_port ()
0f2d19dd
JB
284{
285 return scm_cur_inp;
286}
287
288SCM_PROC(s_current_output_port, "current-output-port", 0, 0, 0, scm_current_output_port);
1cc91f1b 289
0f2d19dd
JB
290SCM
291scm_current_output_port ()
0f2d19dd
JB
292{
293 return scm_cur_outp;
294}
295
296SCM_PROC(s_current_error_port, "current-error-port", 0, 0, 0, scm_current_error_port);
1cc91f1b 297
0f2d19dd
JB
298SCM
299scm_current_error_port ()
0f2d19dd
JB
300{
301 return scm_cur_errp;
302}
303
31614d8e
MD
304SCM_PROC(s_current_load_port, "current-load-port", 0, 0, 0, scm_current_load_port);
305
306SCM
307scm_current_load_port ()
308{
309 return scm_cur_loadp;
310}
311
0f2d19dd 312SCM_PROC(s_set_current_input_port, "set-current-input-port", 1, 0, 0, scm_set_current_input_port);
1cc91f1b 313
0f2d19dd
JB
314SCM
315scm_set_current_input_port (port)
316 SCM port;
0f2d19dd
JB
317{
318 SCM oinp = scm_cur_inp;
319 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_set_current_input_port);
320 scm_cur_inp = port;
321 return oinp;
322}
323
324
325SCM_PROC(s_set_current_output_port, "set-current-output-port", 1, 0, 0, scm_set_current_output_port);
1cc91f1b 326
0f2d19dd
JB
327SCM
328scm_set_current_output_port (port)
329 SCM port;
0f2d19dd
JB
330{
331 SCM ooutp = scm_cur_outp;
78446828 332 port = SCM_COERCE_OUTPORT (port);
0f2d19dd
JB
333 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_set_current_output_port);
334 scm_cur_outp = port;
335 return ooutp;
336}
337
338
339SCM_PROC(s_set_current_error_port, "set-current-error-port", 1, 0, 0, scm_set_current_error_port);
1cc91f1b 340
0f2d19dd
JB
341SCM
342scm_set_current_error_port (port)
343 SCM port;
0f2d19dd
JB
344{
345 SCM oerrp = scm_cur_errp;
78446828 346 port = SCM_COERCE_OUTPORT (port);
0f2d19dd
JB
347 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_set_current_error_port);
348 scm_cur_errp = port;
349 return oerrp;
350}
351
352\f
840ae05d 353/* The port table --- an array of pointers to ports. */
0f2d19dd 354
840ae05d 355scm_port **scm_port_table;
0f2d19dd
JB
356
357int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
358int scm_port_table_room = 20; /* Size of the array. */
359
ee149d03 360/* Add a port to the table. */
1cc91f1b 361
840ae05d 362scm_port *
0f2d19dd
JB
363scm_add_to_port_table (port)
364 SCM port;
0f2d19dd 365{
840ae05d
JB
366 scm_port *entry;
367
0f2d19dd
JB
368 if (scm_port_table_size == scm_port_table_room)
369 {
ee149d03 370 void *newt = realloc ((char *) scm_port_table,
840ae05d 371 (scm_sizet) (sizeof (scm_port *)
ee149d03
JB
372 * scm_port_table_room * 2));
373 if (newt == NULL)
840ae05d
JB
374 scm_memory_error ("scm_add_to_port_table");
375 scm_port_table = (scm_port **) newt;
0f2d19dd
JB
376 scm_port_table_room *= 2;
377 }
840ae05d
JB
378 entry = (scm_port *) malloc (sizeof (scm_port));
379 if (entry == NULL)
380 scm_memory_error ("scm_add_to_port_table");
381
382 entry->port = port;
383 entry->entry = scm_port_table_size;
384 entry->revealed = 0;
385 entry->stream = 0;
386 entry->file_name = SCM_BOOL_F;
387 entry->line_number = 0;
388 entry->column_number = 0;
6c951427
GH
389 entry->putback_buf = 0;
390 entry->putback_buf_size = 0;
840ae05d
JB
391 entry->rw_active = 0;
392
393 scm_port_table[scm_port_table_size] = entry;
394 scm_port_table_size++;
395
396 return entry;
0f2d19dd
JB
397}
398
6c951427 399/* Remove a port from the table and destroy it. */
1cc91f1b 400
0f2d19dd
JB
401void
402scm_remove_from_port_table (port)
403 SCM port;
0f2d19dd 404{
840ae05d 405 scm_port *p = SCM_PTAB_ENTRY (port);
ee1e7e13 406 int i = p->entry;
6c951427 407
ee1e7e13
MD
408 if (i >= scm_port_table_size)
409 scm_wta (port, "Port not in table", "scm_remove_from_port_table");
6c951427
GH
410 if (p->putback_buf)
411 free (p->putback_buf);
840ae05d 412 free (p);
ee1e7e13
MD
413 /* Since we have just freed slot i we can shrink the table by moving
414 the last entry to that slot... */
415 if (i < scm_port_table_size - 1)
0f2d19dd 416 {
ee1e7e13
MD
417 scm_port_table[i] = scm_port_table[scm_port_table_size - 1];
418 scm_port_table[i]->entry = i;
0f2d19dd 419 }
0f2d19dd
JB
420 SCM_SETPTAB_ENTRY (port, 0);
421 scm_port_table_size--;
422}
423
fea6b4ea 424#ifdef GUILE_DEBUG
0f2d19dd
JB
425/* Undocumented functions for debugging. */
426/* Return the number of ports in the table. */
1cc91f1b 427
1146b6cd 428SCM_PROC(s_pt_size, "pt-size", 0, 0, 0, scm_pt_size);
0f2d19dd
JB
429SCM
430scm_pt_size ()
0f2d19dd
JB
431{
432 return SCM_MAKINUM (scm_port_table_size);
433}
434
435/* Return the ith member of the port table. */
1146b6cd 436SCM_PROC(s_pt_member, "pt-member", 1, 0, 0, scm_pt_member);
0f2d19dd
JB
437SCM
438scm_pt_member (member)
439 SCM member;
0f2d19dd
JB
440{
441 int i;
442 SCM_ASSERT (SCM_INUMP (member), member, SCM_ARG1, s_pt_member);
443 i = SCM_INUM (member);
444 if (i < 0 || i >= scm_port_table_size)
445 return SCM_BOOL_F;
446 else
447 return scm_port_table[i]->port;
448}
449#endif
450
451
d68fee48
JB
452\f
453/* Revealed counts --- an oddity inherited from SCSH. */
454
8b13c6b3
GH
455/* Find a port in the table and return its revealed count.
456 Also used by the garbage collector.
0f2d19dd 457 */
1cc91f1b 458
0f2d19dd
JB
459int
460scm_revealed_count (port)
461 SCM port;
0f2d19dd
JB
462{
463 return SCM_REVEALED(port);
464}
465
466
467
468/* Return the revealed count for a port. */
469
470SCM_PROC(s_port_revealed, "port-revealed", 1, 0, 0, scm_port_revealed);
1cc91f1b 471
0f2d19dd
JB
472SCM
473scm_port_revealed (port)
474 SCM port;
0f2d19dd 475{
78446828 476 port = SCM_COERCE_OUTPORT (port);
0f2d19dd 477 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port), port, SCM_ARG1, s_port_revealed);
8b13c6b3 478 return SCM_MAKINUM (scm_revealed_count (port));
0f2d19dd
JB
479}
480
481/* Set the revealed count for a port. */
482SCM_PROC(s_set_port_revealed_x, "set-port-revealed!", 2, 0, 0, scm_set_port_revealed_x);
1cc91f1b 483
0f2d19dd
JB
484SCM
485scm_set_port_revealed_x (port, rcount)
486 SCM port;
487 SCM rcount;
0f2d19dd 488{
78446828 489 port = SCM_COERCE_OUTPORT (port);
0f2d19dd
JB
490 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port), port, SCM_ARG1, s_set_port_revealed_x);
491 SCM_ASSERT (SCM_INUMP (rcount), rcount, SCM_ARG2, s_set_port_revealed_x);
0f2d19dd 492 SCM_REVEALED (port) = SCM_INUM (rcount);
8b13c6b3 493 return SCM_UNSPECIFIED;
0f2d19dd
JB
494}
495
d68fee48
JB
496
497\f
498/* Retrieving a port's mode. */
499
eadd48de
GH
500/* Return the flags that characterize a port based on the mode
501 * string used to open a file for that port.
502 *
503 * See PORT FLAGS in scm.h
504 */
505
506long
507scm_mode_bits (modes)
508 char *modes;
509{
510 return (SCM_OPN
511 | (strchr (modes, 'r') || strchr (modes, '+') ? SCM_RDNG : 0)
512 | ( strchr (modes, 'w')
513 || strchr (modes, 'a')
514 || strchr (modes, '+') ? SCM_WRTNG : 0)
ee149d03
JB
515 | (strchr (modes, '0') ? SCM_BUF0 : 0)
516 | (strchr (modes, 'l') ? SCM_BUFLINE : 0));
eadd48de
GH
517}
518
519
520/* Return the mode flags from an open port.
521 * Some modes such as "append" are only used when opening
522 * a file and are not returned here. */
523
524SCM_PROC(s_port_mode, "port-mode", 1, 0, 0, scm_port_mode);
525
526SCM
527scm_port_mode (port)
528 SCM port;
529{
530 char modes[3];
531 modes[0] = '\0';
78446828
MV
532
533 port = SCM_COERCE_OUTPORT (port);
eadd48de
GH
534 SCM_ASSERT (SCM_NIMP (port) && SCM_OPPORTP (port), port, SCM_ARG1, s_port_mode);
535 if (SCM_CAR (port) & SCM_RDNG) {
536 if (SCM_CAR (port) & SCM_WRTNG)
537 strcpy (modes, "r+");
538 else
539 strcpy (modes, "r");
540 }
541 else if (SCM_CAR (port) & SCM_WRTNG)
542 strcpy (modes, "w");
543 if (SCM_CAR (port) & SCM_BUF0)
544 strcat (modes, "0");
545 return scm_makfromstr (modes, strlen (modes), 0);
546}
547
548
d68fee48
JB
549\f
550/* Closing ports. */
551
0f2d19dd
JB
552/* scm_close_port
553 * Call the close operation on a port object.
eadd48de 554 * see also scm_close.
0f2d19dd
JB
555 */
556SCM_PROC(s_close_port, "close-port", 1, 0, 0, scm_close_port);
1cc91f1b 557
0f2d19dd
JB
558SCM
559scm_close_port (port)
560 SCM port;
0f2d19dd
JB
561{
562 scm_sizet i;
eadd48de
GH
563 int rv;
564
78446828
MV
565 port = SCM_COERCE_OUTPORT (port);
566
341eaef0 567 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port), port, SCM_ARG1,
3c1750f3 568 s_close_port);
0f2d19dd 569 if (SCM_CLOSEDP (port))
eadd48de 570 return SCM_BOOL_F;
0f2d19dd 571 i = SCM_PTOBNUM (port);
0f2d19dd 572 if (scm_ptobs[i].fclose)
ee149d03 573 rv = (scm_ptobs[i].fclose) (port);
eadd48de
GH
574 else
575 rv = 0;
0f2d19dd 576 scm_remove_from_port_table (port);
898a256f 577 SCM_SETAND_CAR (port, ~SCM_OPN);
eadd48de 578 return (rv < 0) ? SCM_BOOL_F : SCM_BOOL_T;
0f2d19dd
JB
579}
580
581SCM_PROC(s_close_all_ports_except, "close-all-ports-except", 0, 0, 1, scm_close_all_ports_except);
1cc91f1b 582
0f2d19dd
JB
583SCM
584scm_close_all_ports_except (ports)
585 SCM ports;
0f2d19dd
JB
586{
587 int i = 0;
588 SCM_ASSERT (SCM_NIMP (ports) && SCM_CONSP (ports), ports, SCM_ARG1, s_close_all_ports_except);
0f2d19dd
JB
589 while (i < scm_port_table_size)
590 {
591 SCM thisport = scm_port_table[i]->port;
592 int found = 0;
593 SCM ports_ptr = ports;
594
595 while (SCM_NNULLP (ports_ptr))
596 {
78446828 597 SCM port = SCM_COERCE_OUTPORT (SCM_CAR (ports_ptr));
0f2d19dd
JB
598 if (i == 0)
599 SCM_ASSERT (SCM_NIMP (port) && SCM_OPPORTP (port), port, SCM_ARG1, s_close_all_ports_except);
600 if (port == thisport)
601 found = 1;
602 ports_ptr = SCM_CDR (ports_ptr);
603 }
604 if (found)
605 i++;
606 else
607 /* i is not to be incremented here. */
608 scm_close_port (thisport);
609 }
0f2d19dd
JB
610 return SCM_UNSPECIFIED;
611}
612
d68fee48
JB
613
614\f
615/* Utter miscellany. Gosh, we should clean this up some time. */
616
0f2d19dd 617SCM_PROC(s_input_port_p, "input-port?", 1, 0, 0, scm_input_port_p);
1cc91f1b 618
0f2d19dd
JB
619SCM
620scm_input_port_p (x)
621 SCM x;
0f2d19dd
JB
622{
623 if (SCM_IMP (x))
624 return SCM_BOOL_F;
625 return SCM_INPORTP (x) ? SCM_BOOL_T : SCM_BOOL_F;
626}
627
628SCM_PROC(s_output_port_p, "output-port?", 1, 0, 0, scm_output_port_p);
1cc91f1b 629
0f2d19dd
JB
630SCM
631scm_output_port_p (x)
632 SCM x;
0f2d19dd
JB
633{
634 if (SCM_IMP (x))
635 return SCM_BOOL_F;
636 return SCM_OUTPORTP (x) ? SCM_BOOL_T : SCM_BOOL_F;
637}
638
639
640SCM_PROC(s_eof_object_p, "eof-object?", 1, 0, 0, scm_eof_object_p);
1cc91f1b 641
0f2d19dd
JB
642SCM
643scm_eof_object_p (x)
644 SCM x;
0f2d19dd 645{
0c32d76c 646 return SCM_EOF_OBJECT_P (x) ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
647}
648
649SCM_PROC(s_force_output, "force-output", 0, 1, 0, scm_force_output);
1cc91f1b 650
0f2d19dd
JB
651SCM
652scm_force_output (port)
653 SCM port;
0f2d19dd
JB
654{
655 if (SCM_UNBNDP (port))
3e877d15 656 port = scm_cur_outp;
0f2d19dd 657 else
78446828
MV
658 {
659 port = SCM_COERCE_OUTPORT (port);
3e877d15
JB
660 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1,
661 s_force_output);
78446828 662 }
ee149d03
JB
663 scm_fflush (port);
664 return SCM_UNSPECIFIED;
0f2d19dd
JB
665}
666
9c29ac66 667SCM_PROC (s_flush_all_ports, "flush-all-ports", 0, 0, 0, scm_flush_all_ports);
89ea5b7c
GH
668SCM
669scm_flush_all_ports (void)
670{
671 int i;
672
673 for (i = 0; i < scm_port_table_size; i++)
674 {
ee149d03
JB
675 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
676 scm_fflush (scm_port_table[i]->port);
89ea5b7c
GH
677 }
678 return SCM_UNSPECIFIED;
679}
0f2d19dd
JB
680
681SCM_PROC(s_read_char, "read-char", 0, 1, 0, scm_read_char);
1cc91f1b 682
0f2d19dd
JB
683SCM
684scm_read_char (port)
685 SCM port;
0f2d19dd
JB
686{
687 int c;
688 if (SCM_UNBNDP (port))
334341aa 689 port = scm_cur_inp;
0f2d19dd
JB
690 else
691 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_read_char);
b7f3516f 692 c = scm_getc (port);
0f2d19dd
JB
693 if (EOF == c)
694 return SCM_EOF_VAL;
695 return SCM_MAKICHR (c);
696}
697
5c070ca7
GH
698/* this should only be called when the read buffer is empty. it
699 tries to refill the buffer. it returns the first char from
700 the port, which is either EOF or *(pt->read_pos). */
6c951427 701int
283a1a0e 702scm_fill_buffer (SCM port)
6c951427 703{
283a1a0e
GH
704 scm_port *pt = SCM_PTAB_ENTRY (port);
705
6c951427
GH
706 if (pt->read_buf == pt->putback_buf)
707 {
708 /* finished reading put-back chars. */
709 pt->read_buf = pt->saved_read_buf;
710 pt->read_pos = pt->saved_read_pos;
711 pt->read_end = pt->saved_read_end;
712 pt->read_buf_size = pt->saved_read_buf_size;
713 if (pt->read_pos < pt->read_end)
5c070ca7 714 return *(pt->read_pos);
6c951427
GH
715 }
716 return scm_ptobs[SCM_PTOBNUM (port)].fill_buffer (port);
717}
718
ee149d03
JB
719int
720scm_getc (port)
0f2d19dd 721 SCM port;
0f2d19dd
JB
722{
723 int c;
840ae05d 724 scm_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 725
840ae05d
JB
726 if (pt->rw_active == SCM_PORT_WRITE)
727 {
6c951427
GH
728 /* may be marginally faster than calling scm_fflush. */
729 scm_ptobs[SCM_PTOBNUM (port)].fflush (port);
840ae05d 730 }
6c951427 731
5c070ca7
GH
732 if (pt->rw_random)
733 pt->rw_active = SCM_PORT_READ;
734
735 if (pt->read_pos >= pt->read_end)
ee149d03 736 {
5c070ca7
GH
737 if (scm_fill_buffer (port) == EOF)
738 return EOF;
ee149d03
JB
739 }
740
5c070ca7 741 c = *(pt->read_pos++);
840ae05d 742
ee149d03
JB
743 if (c == '\n')
744 {
745 SCM_INCLINE (port);
746 }
747 else if (c == '\t')
748 {
749 SCM_TABCOL (port);
750 }
751 else
752 {
753 SCM_INCCOL (port);
754 }
755
756 return c;
0f2d19dd
JB
757}
758
ee149d03
JB
759void
760scm_putc (c, port)
761 int c;
762 SCM port;
763{
840ae05d 764 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 765 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
ee149d03 766
840ae05d 767 if (pt->rw_active == SCM_PORT_READ)
283a1a0e 768 scm_read_flush (port);
6c951427 769
ee149d03 770 *(pt->write_pos++) = (char) c;
6c951427 771
840ae05d
JB
772 if (pt->write_pos == pt->write_end)
773 ptob->fflush (port);
1b9c3dae
GH
774 else
775 {
776 /* check for line-buffering. */
777 if ((SCM_CAR (port) & SCM_BUFLINE)
778 && c == '\n')
779 ptob->fflush (port);
780 }
840ae05d
JB
781
782 if (pt->rw_random)
783 pt->rw_active = SCM_PORT_WRITE;
ee149d03 784}
3cb988bd 785
ee149d03
JB
786void
787scm_puts (s, port)
788 char *s;
3cb988bd
TP
789 SCM port;
790{
840ae05d 791 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 792 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3cb988bd 793
840ae05d 794 if (pt->rw_active == SCM_PORT_READ)
283a1a0e
GH
795 scm_read_flush (port);
796
ee149d03
JB
797 while (*s != 0)
798 {
799 *pt->write_pos++ = *s++;
800 if (pt->write_pos == pt->write_end)
840ae05d 801 ptob->fflush (port);
ee149d03 802 }
ee149d03
JB
803 /* If the port is line-buffered, flush it. */
804 if ((SCM_CAR (port) & SCM_BUFLINE)
805 && memchr (pt->write_buf, '\n', pt->write_pos - pt->write_buf))
840ae05d
JB
806 ptob->fflush (port);
807
808 if (pt->rw_random)
809 pt->rw_active = SCM_PORT_WRITE;
ee149d03 810}
3cb988bd 811
ee149d03
JB
812void
813scm_lfwrite (ptr, size, port)
814 char *ptr;
815 scm_sizet size;
816 SCM port;
817{
840ae05d 818 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 819 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 820
840ae05d 821 if (pt->rw_active == SCM_PORT_READ)
283a1a0e
GH
822 scm_read_flush (port);
823
ee149d03 824 while (size > 0)
3e2043c4 825 {
ee149d03
JB
826 int space = pt->write_end - pt->write_pos;
827 int write_len = (size > space) ? space : size;
828
829 strncpy (pt->write_pos, ptr, write_len);
830 pt->write_pos += write_len;
831 size -= write_len;
832 ptr += write_len;
833 if (write_len == space)
840ae05d 834 ptob->fflush (port);
3e2043c4 835 }
ee149d03
JB
836 /* If the port is line-buffered, flush it. */
837 if ((SCM_CAR (port) & SCM_BUFLINE)
838 && memchr (pt->write_buf, '\n', pt->write_pos - pt->write_buf))
839 (ptob->fflush) (port);
840ae05d
JB
840
841 if (pt->rw_random)
842 pt->rw_active = SCM_PORT_WRITE;
ee149d03 843}
3cb988bd 844
3cb988bd 845
ee149d03
JB
846void
847scm_fflush (port)
848 SCM port;
849{
850 scm_sizet i = SCM_PTOBNUM (port);
851 (scm_ptobs[i].fflush) (port);
852}
853
283a1a0e
GH
854void
855scm_read_flush (port)
856 SCM port;
857{
858 int offset;
859 scm_port *pt = SCM_PTAB_ENTRY (port);
860
861 if (pt->read_buf == pt->putback_buf)
862 {
863 offset = pt->read_end - pt->read_pos;
864 pt->read_buf = pt->saved_read_buf;
865 pt->read_pos = pt->saved_read_pos;
866 pt->read_end = pt->saved_read_end;
867 pt->read_buf_size = pt->saved_read_buf_size;
868 }
869 else
870 offset = 0;
871
872 scm_ptobs[SCM_PTOBNUM (port)].read_flush (port, offset);
873}
874
ee149d03
JB
875\f
876
877
878void
879scm_ungetc (c, port)
880 int c;
881 SCM port;
882{
840ae05d
JB
883 scm_port *pt = SCM_PTAB_ENTRY (port);
884
6c951427
GH
885 if (pt->read_buf == pt->putback_buf)
886 /* already using the put-back buffer. */
887 {
888 /* enlarge putback_buf if necessary. */
889 if (pt->read_end == pt->read_buf + pt->read_buf_size
890 && pt->read_buf == pt->read_pos)
891 {
892 int new_size = pt->read_buf_size * 2;
893 unsigned char *tmp =
894 (unsigned char *) realloc (pt->putback_buf, new_size);
895
896 if (tmp == NULL)
897 scm_memory_error ("scm_ungetc");
898 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
899 pt->read_end = pt->read_buf + pt->read_buf_size;
900 pt->read_buf_size = pt->putback_buf_size = new_size;
901 }
902
903 /* shift any existing bytes to buffer + 1. */
904 if (pt->read_pos == pt->read_end)
905 pt->read_end = pt->read_buf + 1;
906 else if (pt->read_pos != pt->read_buf + 1)
907 {
908 int count = pt->read_end - pt->read_pos;
909
910 memmove (pt->read_buf + 1, pt->read_pos, count);
911 pt->read_end = pt->read_buf + 1 + count;
912 }
913
914 pt->read_pos = pt->read_buf;
915 }
916 else
917 /* switch to the put-back buffer. */
918 {
919 if (pt->putback_buf == NULL)
920 {
921 pt->putback_buf = (char *) malloc (pt->putback_buf_size);
922 if (pt->putback_buf == NULL)
923 scm_memory_error ("scm_ungetc");
924 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
925 }
926
927 pt->saved_read_buf = pt->read_buf;
928 pt->saved_read_pos = pt->read_pos;
929 pt->saved_read_end = pt->read_end;
930 pt->saved_read_buf_size = pt->read_buf_size;
931
932 pt->read_pos = pt->read_buf = pt->putback_buf;
933 pt->read_end = pt->read_buf + 1;
934 pt->read_buf_size = pt->putback_buf_size;
935 }
936
937 *pt->read_buf = c;
ee149d03 938
840ae05d
JB
939 if (pt->rw_random)
940 pt->rw_active = SCM_PORT_READ;
941
ee149d03
JB
942 if (c == '\n')
943 {
944 /* What should col be in this case?
945 * We'll leave it at -1.
946 */
947 SCM_LINUM (port) -= 1;
948 }
949 else
950 SCM_COL(port) -= 1;
951}
952
953
954void
955scm_ungets (s, n, port)
956 char *s;
957 int n;
958 SCM port;
959{
960 /* This is simple minded and inefficient, but unreading strings is
961 * probably not a common operation, and remember that line and
962 * column numbers have to be handled...
963 *
964 * Please feel free to write an optimized version!
965 */
966 while (n--)
967 scm_ungetc (s[n], port);
968}
969
970
971SCM_PROC(s_peek_char, "peek-char", 0, 1, 0, scm_peek_char);
972
973SCM
974scm_peek_char (port)
975 SCM port;
976{
977 int c;
978 if (SCM_UNBNDP (port))
979 port = scm_cur_inp;
980 else
981 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_peek_char);
982 c = scm_getc (port);
983 if (EOF == c)
984 return SCM_EOF_VAL;
985 scm_ungetc (c, port);
986 return SCM_MAKICHR (c);
3cb988bd
TP
987}
988
0f2d19dd 989SCM_PROC (s_unread_char, "unread-char", 2, 0, 0, scm_unread_char);
1cc91f1b 990
0f2d19dd
JB
991SCM
992scm_unread_char (cobj, port)
993 SCM cobj;
994 SCM port;
0f2d19dd
JB
995{
996 int c;
997
998 SCM_ASSERT (SCM_ICHRP (cobj), cobj, SCM_ARG1, s_unread_char);
999
1000 if (SCM_UNBNDP (port))
1001 port = scm_cur_inp;
1002 else
1003 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG2, s_unread_char);
1004
1005
1006 c = SCM_ICHR (cobj);
1007
b7f3516f 1008 scm_ungetc (c, port);
0f2d19dd
JB
1009 return cobj;
1010}
1011
ee1e7e13
MD
1012SCM_PROC (s_unread_string, "unread-string", 2, 0, 0, scm_unread_string);
1013
1014SCM
1015scm_unread_string (str, port)
1016 SCM str;
1017 SCM port;
1018{
d1c90db5 1019 SCM_ASSERT (SCM_NIMP (str) && SCM_STRINGP (str),
ee1e7e13
MD
1020 str, SCM_ARG1, s_unread_string);
1021
1022 if (SCM_UNBNDP (port))
1023 port = scm_cur_inp;
1024 else
1025 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port),
1026 port, SCM_ARG2, s_unread_string);
1027
d1c90db5 1028 scm_ungets (SCM_ROUCHARS (str), SCM_LENGTH (str), port);
ee1e7e13
MD
1029
1030 return str;
1031}
1032
840ae05d
JB
1033SCM_PROC (s_lseek, "lseek", 3, 0, 0, scm_lseek);
1034SCM
1035scm_lseek (SCM object, SCM offset, SCM whence)
1036{
1037 off_t off;
1038 off_t rv;
1039 int how;
1040
1041 object = SCM_COERCE_OUTPORT (object);
1042
1043 off = scm_num2long (offset, (char *)SCM_ARG2, s_lseek);
1044 SCM_ASSERT (SCM_INUMP (whence), whence, SCM_ARG3, s_lseek);
1045 how = SCM_INUM (whence);
1046 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1047 scm_out_of_range (s_lseek, whence);
1048 if (SCM_NIMP (object) && SCM_OPPORTP (object))
1049 {
1050 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1051 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
840ae05d
JB
1052
1053 if (!ptob->seek)
1054 scm_misc_error (s_lseek, "port is not seekable",
1055 scm_cons (object, SCM_EOL));
1056 else
1057 {
1058 if (pt->rw_active == SCM_PORT_READ)
283a1a0e 1059 scm_read_flush (object);
840ae05d
JB
1060 else if (pt->rw_active == SCM_PORT_WRITE)
1061 ptob->fflush (object);
1062
1063 rv = ptob->seek (object, off, how);
840ae05d
JB
1064 }
1065 }
1066 else /* file descriptor?. */
1067 {
1068 SCM_ASSERT (SCM_INUMP (object), object, SCM_ARG1, s_lseek);
1069 rv = lseek (SCM_INUM (object), off, how);
1070 if (rv == -1)
1071 scm_syserror (s_lseek);
1072 }
1073 return scm_long2num (rv);
1074}
1075
69bc9ff3 1076SCM_PROC (s_truncate_file, "truncate-file", 1, 1, 0, scm_truncate_file);
840ae05d
JB
1077
1078SCM
69bc9ff3 1079scm_truncate_file (SCM object, SCM length)
840ae05d 1080{
69bc9ff3
GH
1081 int rv;
1082 off_t c_length;
1083
1084 /* object can be a port, fdes or filename. */
840ae05d 1085
840ae05d
JB
1086 if (SCM_UNBNDP (length))
1087 {
69bc9ff3
GH
1088 /* must supply length if object is a filename. */
1089 if (SCM_NIMP (object) && SCM_ROSTRINGP (object))
1090 scm_wrong_num_args (scm_makfrom0str (s_truncate_file));
1091
1092 length = scm_lseek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
840ae05d 1093 }
69bc9ff3
GH
1094 c_length = scm_num2long (length, (char *)SCM_ARG2, s_truncate_file);
1095 if (c_length < 0)
1096 scm_misc_error (s_truncate_file, "negative offset", SCM_EOL);
3fe6190f 1097
69bc9ff3
GH
1098 object = SCM_COERCE_OUTPORT (object);
1099 if (SCM_INUMP (object))
1100 {
1101 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1102 }
1103 else if (SCM_NIMP (object) && SCM_OPOUTPORTP (object))
1104 {
1105 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1106 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3
GH
1107
1108 if (!ptob->ftruncate)
1109 scm_misc_error (s_truncate_file, "port is not truncatable", SCM_EOL);
1110 if (pt->rw_active == SCM_PORT_READ)
1111 scm_read_flush (object);
1112 else if (pt->rw_active == SCM_PORT_WRITE)
1113 ptob->fflush (object);
1114
1115 ptob->ftruncate (object, c_length);
1116 rv = 0;
1117 }
1118 else
1119 {
1120 SCM_ASSERT (SCM_NIMP (object) && SCM_ROSTRINGP (object),
1121 object, SCM_ARG1, s_truncate_file);
1122 SCM_COERCE_SUBSTR (object);
1123 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), c_length));
1124 }
1125 if (rv == -1)
1126 scm_syserror (s_truncate_file);
840ae05d
JB
1127 return SCM_UNSPECIFIED;
1128}
1129
360fc44c 1130SCM_PROC (s_port_line, "port-line", 1, 0, 0, scm_port_line);
1cc91f1b 1131
0f2d19dd 1132SCM
d14af9f2 1133scm_port_line (port)
0f2d19dd 1134 SCM port;
0f2d19dd 1135{
78446828 1136 port = SCM_COERCE_OUTPORT (port);
360fc44c
MD
1137 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1138 port,
1139 SCM_ARG1,
1140 s_port_line);
1141 return SCM_MAKINUM (SCM_LINUM (port));
0f2d19dd
JB
1142}
1143
360fc44c 1144SCM_PROC (s_set_port_line_x, "set-port-line!", 2, 0, 0, scm_set_port_line_x);
d043d8c2
MD
1145
1146SCM
1147scm_set_port_line_x (port, line)
1148 SCM port;
1149 SCM line;
1150{
360fc44c
MD
1151 port = SCM_COERCE_OUTPORT (port);
1152 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1153 port,
1154 SCM_ARG1,
1155 s_set_port_line_x);
1156 SCM_ASSERT (SCM_INUMP (line), line, SCM_ARG2, s_set_port_line_x);
d043d8c2
MD
1157 return SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1158}
1159
360fc44c 1160SCM_PROC (s_port_column, "port-column", 1, 0, 0, scm_port_column);
1cc91f1b 1161
0f2d19dd 1162SCM
d14af9f2 1163scm_port_column (port)
0f2d19dd 1164 SCM port;
0f2d19dd 1165{
78446828 1166 port = SCM_COERCE_OUTPORT (port);
360fc44c
MD
1167 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1168 port,
1169 SCM_ARG1,
1170 s_port_column);
1171 return SCM_MAKINUM (SCM_COL (port));
0f2d19dd
JB
1172}
1173
360fc44c 1174SCM_PROC (s_set_port_column_x, "set-port-column!", 2, 0, 0, scm_set_port_column_x);
d043d8c2
MD
1175
1176SCM
1177scm_set_port_column_x (port, column)
1178 SCM port;
1179 SCM column;
1180{
360fc44c
MD
1181 port = SCM_COERCE_OUTPORT (port);
1182 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1183 port,
1184 SCM_ARG1,
1185 s_set_port_column_x);
1186 SCM_ASSERT (SCM_INUMP (column), column, SCM_ARG2, s_set_port_column_x);
d043d8c2
MD
1187 return SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1188}
1189
360fc44c 1190SCM_PROC (s_port_filename, "port-filename", 1, 0, 0, scm_port_filename);
1cc91f1b 1191
0f2d19dd 1192SCM
d14af9f2 1193scm_port_filename (port)
0f2d19dd 1194 SCM port;
0f2d19dd 1195{
78446828 1196 port = SCM_COERCE_OUTPORT (port);
360fc44c
MD
1197 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1198 port,
1199 SCM_ARG1,
1200 s_port_filename);
1201 return SCM_PTAB_ENTRY (port)->file_name;
0f2d19dd
JB
1202}
1203
360fc44c 1204SCM_PROC (s_set_port_filename_x, "set-port-filename!", 2, 0, 0, scm_set_port_filename_x);
1cc91f1b 1205
d14af9f2
MD
1206SCM
1207scm_set_port_filename_x (port, filename)
1208 SCM port;
1209 SCM filename;
d14af9f2 1210{
360fc44c
MD
1211 port = SCM_COERCE_OUTPORT (port);
1212 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1213 port,
1214 SCM_ARG1,
1215 s_set_port_filename_x);
1216 /* We allow the user to set the filename to whatever he likes. */
d14af9f2
MD
1217 return SCM_PTAB_ENTRY (port)->file_name = filename;
1218}
1219
0f2d19dd
JB
1220#ifndef ttyname
1221extern char * ttyname();
1222#endif
1223
f12733c9
MD
1224void
1225scm_print_port_mode (SCM exp, SCM port)
1226{
1227 scm_puts (SCM_CLOSEDP (exp)
1228 ? "closed: "
1229 : (SCM_RDNG & SCM_CAR (exp)
1230 ? (SCM_WRTNG & SCM_CAR (exp)
1231 ? "input-output: "
1232 : "input: ")
1233 : (SCM_WRTNG & SCM_CAR (exp)
1234 ? "output: "
1235 : "bogus: ")),
1236 port);
1237}
1cc91f1b 1238
f12733c9
MD
1239int
1240scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 1241{
f12733c9
MD
1242 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1243 if (!type)
1244 type = "port";
b7f3516f 1245 scm_puts ("#<", port);
f12733c9 1246 scm_print_port_mode (exp, port);
b7f3516f
TT
1247 scm_puts (type, port);
1248 scm_putc (' ', port);
f12733c9 1249 scm_intprint (SCM_CDR (exp), 16, port);
b7f3516f 1250 scm_putc ('>', port);
f12733c9 1251 return 1;
0f2d19dd
JB
1252}
1253
f12733c9
MD
1254extern void scm_make_fptob ();
1255extern void scm_make_stptob ();
1256extern void scm_make_sfptob ();
1cc91f1b 1257
0f2d19dd
JB
1258void
1259scm_ports_prehistory ()
0f2d19dd
JB
1260{
1261 scm_numptob = 0;
f12733c9 1262 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
0f2d19dd
JB
1263
1264 /* WARNING: These scm_newptob calls must be done in this order.
1265 * They must agree with the port declarations in tags.h.
1266 */
f12733c9
MD
1267 /* scm_tc16_fport = */ scm_make_fptob ();
1268 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1269 /* scm_tc16_strport = */ scm_make_stptob ();
1270 /* scm_tc16_sfport = */ scm_make_sfptob ();
0f2d19dd 1271}
0f2d19dd
JB
1272
1273\f
ee149d03 1274
d68fee48 1275/* Void ports. */
0f2d19dd 1276
f12733c9 1277long scm_tc16_void_port = 0;
0f2d19dd 1278
ee149d03 1279static void
0f88a8f3 1280flush_void_port (SCM port)
0f2d19dd 1281{
3cb988bd 1282}
1cc91f1b 1283
283a1a0e
GH
1284static void
1285read_flush_void_port (SCM port, int offset)
1286{
1287}
1288
0f2d19dd
JB
1289SCM
1290scm_void_port (mode_str)
1291 char * mode_str;
0f2d19dd
JB
1292{
1293 int mode_bits;
1294 SCM answer;
840ae05d 1295 scm_port * pt;
0f2d19dd
JB
1296
1297 SCM_NEWCELL (answer);
1298 SCM_DEFER_INTS;
1299 mode_bits = scm_mode_bits (mode_str);
1300 pt = scm_add_to_port_table (answer);
0f2d19dd 1301 SCM_SETPTAB_ENTRY (answer, pt);
ee149d03
JB
1302 SCM_SETSTREAM (answer, 0);
1303 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
0f2d19dd
JB
1304 SCM_ALLOW_INTS;
1305 return answer;
1306}
1307
1308
1309SCM_PROC (s_sys_make_void_port, "%make-void-port", 1, 0, 0, scm_sys_make_void_port);
1cc91f1b 1310
0f2d19dd
JB
1311SCM
1312scm_sys_make_void_port (mode)
1313 SCM mode;
0f2d19dd 1314{
89958ad0 1315 SCM_ASSERT (SCM_NIMP (mode) && SCM_ROSTRINGP (mode), mode,
0f2d19dd
JB
1316 SCM_ARG1, s_sys_make_void_port);
1317
89958ad0 1318 SCM_COERCE_SUBSTR (mode);
0f2d19dd
JB
1319 return scm_void_port (SCM_ROCHARS (mode));
1320}
1321
0f2d19dd 1322\f
89545eba 1323/* Initialization. */
1cc91f1b 1324
0f2d19dd
JB
1325void
1326scm_init_ports ()
0f2d19dd 1327{
840ae05d
JB
1328 /* lseek() symbols. */
1329 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1330 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1331 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1332
f12733c9 1333 scm_tc16_void_port = scm_make_port_type ("void", 0, 0);
0f2d19dd
JB
1334#include "ports.x"
1335}