* gh_data.c, ports.c, strop.c: Alternatively use bcopy if memmove
[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 91/*
f12733c9 92 * We choose to use an interface similar to the smob interface with
affc96b5 93 * fill_input and write as standard fields, passed to the port
f12733c9
MD
94 * type constructor, and optional fields set by setters.
95 */
96
97static void flush_void_port (SCM port);
affc96b5 98static void end_input_void_port (SCM port, int offset);
31703ab8 99static void write_void_port (SCM port, void *data, size_t size);
0f2d19dd 100
0f2d19dd 101long
f12733c9 102scm_make_port_type (char *name,
affc96b5
GH
103 int (*fill_input) (SCM port),
104 void (*write) (SCM port, void *data, size_t size))
0f2d19dd
JB
105{
106 char *tmp;
107 if (255 <= scm_numptob)
108 goto ptoberr;
f12733c9
MD
109 SCM_DEFER_INTS;
110 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
111 (1 + scm_numptob)
112 * sizeof (scm_ptob_descriptor)));
0f2d19dd
JB
113 if (tmp)
114 {
f12733c9 115 scm_ptobs = (scm_ptob_descriptor *) tmp;
affc96b5 116
f12733c9
MD
117 scm_ptobs[scm_numptob].name = name;
118 scm_ptobs[scm_numptob].mark = 0;
119 scm_ptobs[scm_numptob].free = scm_free0;
120 scm_ptobs[scm_numptob].print = scm_port_print;
121 scm_ptobs[scm_numptob].equalp = 0;
affc96b5
GH
122 scm_ptobs[scm_numptob].close = 0;
123
124 scm_ptobs[scm_numptob].write = write;
125 scm_ptobs[scm_numptob].flush = flush_void_port;
126
127 scm_ptobs[scm_numptob].end_input = end_input_void_port;
128 scm_ptobs[scm_numptob].fill_input = fill_input;
129 scm_ptobs[scm_numptob].input_waiting = 0;
130
f12733c9 131 scm_ptobs[scm_numptob].seek = 0;
affc96b5
GH
132 scm_ptobs[scm_numptob].truncate = 0;
133
0f2d19dd
JB
134 scm_numptob++;
135 }
f12733c9 136 SCM_ALLOW_INTS;
0f2d19dd 137 if (!tmp)
f12733c9
MD
138 ptoberr:scm_wta (SCM_MAKINUM ((long) scm_numptob),
139 (char *) SCM_NALLOC, "scm_make_port_type");
140 /* Make a class object if Goops is present */
141 if (scm_port_class)
142 scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
0f2d19dd
JB
143 return scm_tc7_port + (scm_numptob - 1) * 256;
144}
145
f12733c9 146void
6c747373 147scm_set_port_mark (long tc, SCM (*mark) (SCM))
f12733c9
MD
148{
149 scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
150}
151
152void
6c747373 153scm_set_port_free (long tc, scm_sizet (*free) (SCM))
f12733c9
MD
154{
155 scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
156}
157
158void
6c747373 159scm_set_port_print (long tc, int (*print) (SCM exp, SCM port,
f12733c9
MD
160 scm_print_state *pstate))
161{
162 scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
163}
164
165void
6c747373 166scm_set_port_equalp (long tc, SCM (*equalp) (SCM, SCM))
f12733c9
MD
167{
168 scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
169}
170
31703ab8 171void
affc96b5 172scm_set_port_flush (long tc, void (*flush) (SCM port))
31703ab8 173{
affc96b5 174 scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
31703ab8
GH
175}
176
f12733c9 177void
affc96b5 178scm_set_port_end_input (long tc, void (*end_input) (SCM port, int offset))
f12733c9 179{
affc96b5 180 scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
f12733c9
MD
181}
182
183void
6c747373 184scm_set_port_close (long tc, int (*close) (SCM))
f12733c9 185{
affc96b5 186 scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
f12733c9
MD
187}
188
189void
6c747373 190scm_set_port_seek (long tc, off_t (*seek) (SCM port,
f12733c9
MD
191 off_t OFFSET,
192 int WHENCE))
193{
194 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
195}
196
197void
6c747373 198scm_set_port_truncate (long tc, void (*truncate) (SCM port, off_t length))
f12733c9 199{
affc96b5 200 scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
f12733c9
MD
201}
202
203void
affc96b5 204scm_set_port_input_waiting (long tc, int (*input_waiting) (SCM))
f12733c9 205{
affc96b5 206 scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
f12733c9
MD
207}
208
0f2d19dd 209\f
0f2d19dd 210
44493941 211SCM_PROC(s_char_ready_p, "char-ready?", 0, 1, 0, scm_char_ready_p);
1cc91f1b 212
0f2d19dd
JB
213SCM
214scm_char_ready_p (port)
215 SCM port;
0f2d19dd 216{
ae4c4016 217 scm_port *pt;
6c951427 218
0f2d19dd
JB
219 if (SCM_UNBNDP (port))
220 port = scm_cur_inp;
221 else
d68fee48
JB
222 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1,
223 s_char_ready_p);
224
ae4c4016
JB
225 pt = SCM_PTAB_ENTRY (port);
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
affc96b5
GH
238 if (ptob->input_waiting)
239 return (ptob->input_waiting (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;
61e452ba 391 entry->rw_active = SCM_PORT_NEITHER;
840ae05d
JB
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);
affc96b5
GH
572 if (scm_ptobs[i].close)
573 rv = (scm_ptobs[i].close) (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))
4a94d8ca 624 return SCM_BOOL_F;
0f2d19dd
JB
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))
4a94d8ca
MD
635 return SCM_BOOL_F;
636 if (SCM_PORT_WITH_PS_P (x))
637 x = SCM_PORT_WITH_PS_PORT (x);
0f2d19dd
JB
638 return SCM_OUTPORTP (x) ? SCM_BOOL_T : SCM_BOOL_F;
639}
640
641
642SCM_PROC(s_eof_object_p, "eof-object?", 1, 0, 0, scm_eof_object_p);
1cc91f1b 643
0f2d19dd
JB
644SCM
645scm_eof_object_p (x)
646 SCM x;
0f2d19dd 647{
0c32d76c 648 return SCM_EOF_OBJECT_P (x) ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
649}
650
651SCM_PROC(s_force_output, "force-output", 0, 1, 0, scm_force_output);
1cc91f1b 652
0f2d19dd
JB
653SCM
654scm_force_output (port)
655 SCM port;
0f2d19dd
JB
656{
657 if (SCM_UNBNDP (port))
3e877d15 658 port = scm_cur_outp;
0f2d19dd 659 else
78446828
MV
660 {
661 port = SCM_COERCE_OUTPORT (port);
3e877d15
JB
662 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1,
663 s_force_output);
78446828 664 }
affc96b5 665 scm_flush (port);
ee149d03 666 return SCM_UNSPECIFIED;
0f2d19dd
JB
667}
668
9c29ac66 669SCM_PROC (s_flush_all_ports, "flush-all-ports", 0, 0, 0, scm_flush_all_ports);
89ea5b7c
GH
670SCM
671scm_flush_all_ports (void)
672{
673 int i;
674
675 for (i = 0; i < scm_port_table_size; i++)
676 {
ee149d03 677 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
affc96b5 678 scm_flush (scm_port_table[i]->port);
89ea5b7c
GH
679 }
680 return SCM_UNSPECIFIED;
681}
0f2d19dd
JB
682
683SCM_PROC(s_read_char, "read-char", 0, 1, 0, scm_read_char);
1cc91f1b 684
0f2d19dd
JB
685SCM
686scm_read_char (port)
687 SCM port;
0f2d19dd
JB
688{
689 int c;
690 if (SCM_UNBNDP (port))
334341aa 691 port = scm_cur_inp;
0f2d19dd
JB
692 else
693 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_read_char);
b7f3516f 694 c = scm_getc (port);
0f2d19dd
JB
695 if (EOF == c)
696 return SCM_EOF_VAL;
697 return SCM_MAKICHR (c);
698}
699
5c070ca7 700/* this should only be called when the read buffer is empty. it
affc96b5 701 tries to refill the read buffer. it returns the first char from
5c070ca7 702 the port, which is either EOF or *(pt->read_pos). */
6c951427 703int
affc96b5 704scm_fill_input (SCM port)
6c951427 705{
283a1a0e
GH
706 scm_port *pt = SCM_PTAB_ENTRY (port);
707
6c951427
GH
708 if (pt->read_buf == pt->putback_buf)
709 {
710 /* finished reading put-back chars. */
711 pt->read_buf = pt->saved_read_buf;
712 pt->read_pos = pt->saved_read_pos;
713 pt->read_end = pt->saved_read_end;
714 pt->read_buf_size = pt->saved_read_buf_size;
715 if (pt->read_pos < pt->read_end)
5c070ca7 716 return *(pt->read_pos);
6c951427 717 }
affc96b5 718 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
719}
720
ee149d03
JB
721int
722scm_getc (port)
0f2d19dd 723 SCM port;
0f2d19dd
JB
724{
725 int c;
840ae05d 726 scm_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 727
840ae05d
JB
728 if (pt->rw_active == SCM_PORT_WRITE)
729 {
affc96b5
GH
730 /* may be marginally faster than calling scm_flush. */
731 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
840ae05d 732 }
6c951427 733
5c070ca7
GH
734 if (pt->rw_random)
735 pt->rw_active = SCM_PORT_READ;
736
737 if (pt->read_pos >= pt->read_end)
ee149d03 738 {
affc96b5 739 if (scm_fill_input (port) == EOF)
5c070ca7 740 return EOF;
ee149d03
JB
741 }
742
5c070ca7 743 c = *(pt->read_pos++);
840ae05d 744
ee149d03
JB
745 if (c == '\n')
746 {
747 SCM_INCLINE (port);
748 }
749 else if (c == '\t')
750 {
751 SCM_TABCOL (port);
752 }
753 else
754 {
755 SCM_INCCOL (port);
756 }
757
758 return c;
0f2d19dd
JB
759}
760
ee149d03
JB
761void
762scm_putc (c, port)
265e6a4d 763 char c;
ee149d03
JB
764 SCM port;
765{
265e6a4d 766 scm_lfwrite (&c, 1, port);
ee149d03 767}
3cb988bd 768
ee149d03
JB
769void
770scm_puts (s, port)
771 char *s;
3cb988bd
TP
772 SCM port;
773{
265e6a4d 774 scm_lfwrite (s, strlen (s), port);
ee149d03 775}
3cb988bd 776
ee149d03
JB
777void
778scm_lfwrite (ptr, size, port)
779 char *ptr;
780 scm_sizet size;
781 SCM port;
782{
840ae05d 783 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 784 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 785
840ae05d 786 if (pt->rw_active == SCM_PORT_READ)
affc96b5 787 scm_end_input (port);
283a1a0e 788
31703ab8 789 ptob->write (port, ptr, size);
840ae05d
JB
790
791 if (pt->rw_random)
792 pt->rw_active = SCM_PORT_WRITE;
ee149d03 793}
3cb988bd 794
3cb988bd 795
ee149d03 796void
affc96b5 797scm_flush (port)
ee149d03
JB
798 SCM port;
799{
800 scm_sizet i = SCM_PTOBNUM (port);
affc96b5 801 (scm_ptobs[i].flush) (port);
ee149d03
JB
802}
803
283a1a0e 804void
affc96b5 805scm_end_input (port)
283a1a0e
GH
806 SCM port;
807{
808 int offset;
809 scm_port *pt = SCM_PTAB_ENTRY (port);
810
811 if (pt->read_buf == pt->putback_buf)
812 {
813 offset = pt->read_end - pt->read_pos;
814 pt->read_buf = pt->saved_read_buf;
815 pt->read_pos = pt->saved_read_pos;
816 pt->read_end = pt->saved_read_end;
817 pt->read_buf_size = pt->saved_read_buf_size;
818 }
819 else
820 offset = 0;
821
affc96b5 822 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
823}
824
ee149d03
JB
825\f
826
827
828void
829scm_ungetc (c, port)
830 int c;
831 SCM port;
832{
840ae05d
JB
833 scm_port *pt = SCM_PTAB_ENTRY (port);
834
6c951427
GH
835 if (pt->read_buf == pt->putback_buf)
836 /* already using the put-back buffer. */
837 {
838 /* enlarge putback_buf if necessary. */
839 if (pt->read_end == pt->read_buf + pt->read_buf_size
840 && pt->read_buf == pt->read_pos)
841 {
842 int new_size = pt->read_buf_size * 2;
843 unsigned char *tmp =
844 (unsigned char *) realloc (pt->putback_buf, new_size);
845
846 if (tmp == NULL)
847 scm_memory_error ("scm_ungetc");
848 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
849 pt->read_end = pt->read_buf + pt->read_buf_size;
850 pt->read_buf_size = pt->putback_buf_size = new_size;
851 }
852
853 /* shift any existing bytes to buffer + 1. */
854 if (pt->read_pos == pt->read_end)
855 pt->read_end = pt->read_buf + 1;
856 else if (pt->read_pos != pt->read_buf + 1)
857 {
858 int count = pt->read_end - pt->read_pos;
859
860 memmove (pt->read_buf + 1, pt->read_pos, count);
861 pt->read_end = pt->read_buf + 1 + count;
862 }
863
864 pt->read_pos = pt->read_buf;
865 }
866 else
867 /* switch to the put-back buffer. */
868 {
869 if (pt->putback_buf == NULL)
870 {
6e2e75db 871 pt->putback_buf = (char *) malloc (SCM_INITIAL_PUTBACK_BUF_SIZE);
6c951427
GH
872 if (pt->putback_buf == NULL)
873 scm_memory_error ("scm_ungetc");
874 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
875 }
876
877 pt->saved_read_buf = pt->read_buf;
878 pt->saved_read_pos = pt->read_pos;
879 pt->saved_read_end = pt->read_end;
880 pt->saved_read_buf_size = pt->read_buf_size;
881
882 pt->read_pos = pt->read_buf = pt->putback_buf;
883 pt->read_end = pt->read_buf + 1;
884 pt->read_buf_size = pt->putback_buf_size;
885 }
886
887 *pt->read_buf = c;
ee149d03 888
840ae05d
JB
889 if (pt->rw_random)
890 pt->rw_active = SCM_PORT_READ;
891
ee149d03
JB
892 if (c == '\n')
893 {
894 /* What should col be in this case?
895 * We'll leave it at -1.
896 */
897 SCM_LINUM (port) -= 1;
898 }
899 else
900 SCM_COL(port) -= 1;
901}
902
903
904void
905scm_ungets (s, n, port)
906 char *s;
907 int n;
908 SCM port;
909{
910 /* This is simple minded and inefficient, but unreading strings is
911 * probably not a common operation, and remember that line and
912 * column numbers have to be handled...
913 *
914 * Please feel free to write an optimized version!
915 */
916 while (n--)
917 scm_ungetc (s[n], port);
918}
919
920
921SCM_PROC(s_peek_char, "peek-char", 0, 1, 0, scm_peek_char);
922
923SCM
924scm_peek_char (port)
925 SCM port;
926{
927 int c;
928 if (SCM_UNBNDP (port))
929 port = scm_cur_inp;
930 else
931 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_peek_char);
932 c = scm_getc (port);
933 if (EOF == c)
934 return SCM_EOF_VAL;
935 scm_ungetc (c, port);
936 return SCM_MAKICHR (c);
3cb988bd
TP
937}
938
0f2d19dd 939SCM_PROC (s_unread_char, "unread-char", 2, 0, 0, scm_unread_char);
1cc91f1b 940
0f2d19dd
JB
941SCM
942scm_unread_char (cobj, port)
943 SCM cobj;
944 SCM port;
0f2d19dd
JB
945{
946 int c;
947
948 SCM_ASSERT (SCM_ICHRP (cobj), cobj, SCM_ARG1, s_unread_char);
949
950 if (SCM_UNBNDP (port))
951 port = scm_cur_inp;
952 else
953 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG2, s_unread_char);
954
955
956 c = SCM_ICHR (cobj);
957
b7f3516f 958 scm_ungetc (c, port);
0f2d19dd
JB
959 return cobj;
960}
961
ee1e7e13
MD
962SCM_PROC (s_unread_string, "unread-string", 2, 0, 0, scm_unread_string);
963
964SCM
965scm_unread_string (str, port)
966 SCM str;
967 SCM port;
968{
d1c90db5 969 SCM_ASSERT (SCM_NIMP (str) && SCM_STRINGP (str),
ee1e7e13
MD
970 str, SCM_ARG1, s_unread_string);
971
972 if (SCM_UNBNDP (port))
973 port = scm_cur_inp;
974 else
975 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port),
976 port, SCM_ARG2, s_unread_string);
977
d1c90db5 978 scm_ungets (SCM_ROUCHARS (str), SCM_LENGTH (str), port);
ee1e7e13
MD
979
980 return str;
981}
982
c94577b4 983SCM_PROC (s_seek, "seek", 3, 0, 0, scm_seek);
840ae05d 984SCM
c94577b4 985scm_seek (SCM object, SCM offset, SCM whence)
840ae05d
JB
986{
987 off_t off;
988 off_t rv;
989 int how;
990
991 object = SCM_COERCE_OUTPORT (object);
992
c94577b4
GH
993 off = scm_num2long (offset, (char *)SCM_ARG2, s_seek);
994 SCM_ASSERT (SCM_INUMP (whence), whence, SCM_ARG3, s_seek);
840ae05d
JB
995 how = SCM_INUM (whence);
996 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
c94577b4 997 scm_out_of_range (s_seek, whence);
840ae05d
JB
998 if (SCM_NIMP (object) && SCM_OPPORTP (object))
999 {
1000 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1001 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
840ae05d
JB
1002
1003 if (!ptob->seek)
c94577b4 1004 scm_misc_error (s_seek, "port is not seekable",
840ae05d
JB
1005 scm_cons (object, SCM_EOL));
1006 else
1007 {
1008 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1009 scm_end_input (object);
840ae05d 1010 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1011 ptob->flush (object);
840ae05d
JB
1012
1013 rv = ptob->seek (object, off, how);
840ae05d
JB
1014 }
1015 }
1016 else /* file descriptor?. */
1017 {
c94577b4 1018 SCM_ASSERT (SCM_INUMP (object), object, SCM_ARG1, s_seek);
840ae05d
JB
1019 rv = lseek (SCM_INUM (object), off, how);
1020 if (rv == -1)
c94577b4 1021 scm_syserror (s_seek);
840ae05d
JB
1022 }
1023 return scm_long2num (rv);
1024}
1025
69bc9ff3 1026SCM_PROC (s_truncate_file, "truncate-file", 1, 1, 0, scm_truncate_file);
840ae05d
JB
1027
1028SCM
69bc9ff3 1029scm_truncate_file (SCM object, SCM length)
840ae05d 1030{
69bc9ff3
GH
1031 int rv;
1032 off_t c_length;
1033
1034 /* object can be a port, fdes or filename. */
840ae05d 1035
840ae05d
JB
1036 if (SCM_UNBNDP (length))
1037 {
69bc9ff3
GH
1038 /* must supply length if object is a filename. */
1039 if (SCM_NIMP (object) && SCM_ROSTRINGP (object))
1040 scm_wrong_num_args (scm_makfrom0str (s_truncate_file));
1041
c94577b4 1042 length = scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
840ae05d 1043 }
69bc9ff3
GH
1044 c_length = scm_num2long (length, (char *)SCM_ARG2, s_truncate_file);
1045 if (c_length < 0)
1046 scm_misc_error (s_truncate_file, "negative offset", SCM_EOL);
3fe6190f 1047
69bc9ff3
GH
1048 object = SCM_COERCE_OUTPORT (object);
1049 if (SCM_INUMP (object))
1050 {
1051 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1052 }
1053 else if (SCM_NIMP (object) && SCM_OPOUTPORTP (object))
1054 {
1055 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1056 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1057
affc96b5 1058 if (!ptob->truncate)
69bc9ff3
GH
1059 scm_misc_error (s_truncate_file, "port is not truncatable", SCM_EOL);
1060 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1061 scm_end_input (object);
69bc9ff3 1062 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1063 ptob->flush (object);
69bc9ff3 1064
affc96b5 1065 ptob->truncate (object, c_length);
69bc9ff3
GH
1066 rv = 0;
1067 }
1068 else
1069 {
1070 SCM_ASSERT (SCM_NIMP (object) && SCM_ROSTRINGP (object),
1071 object, SCM_ARG1, s_truncate_file);
1072 SCM_COERCE_SUBSTR (object);
1073 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), c_length));
1074 }
1075 if (rv == -1)
1076 scm_syserror (s_truncate_file);
840ae05d
JB
1077 return SCM_UNSPECIFIED;
1078}
1079
360fc44c 1080SCM_PROC (s_port_line, "port-line", 1, 0, 0, scm_port_line);
1cc91f1b 1081
0f2d19dd 1082SCM
d14af9f2 1083scm_port_line (port)
0f2d19dd 1084 SCM port;
0f2d19dd 1085{
78446828 1086 port = SCM_COERCE_OUTPORT (port);
360fc44c
MD
1087 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1088 port,
1089 SCM_ARG1,
1090 s_port_line);
1091 return SCM_MAKINUM (SCM_LINUM (port));
0f2d19dd
JB
1092}
1093
360fc44c 1094SCM_PROC (s_set_port_line_x, "set-port-line!", 2, 0, 0, scm_set_port_line_x);
d043d8c2
MD
1095
1096SCM
1097scm_set_port_line_x (port, line)
1098 SCM port;
1099 SCM line;
1100{
360fc44c
MD
1101 port = SCM_COERCE_OUTPORT (port);
1102 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1103 port,
1104 SCM_ARG1,
1105 s_set_port_line_x);
1106 SCM_ASSERT (SCM_INUMP (line), line, SCM_ARG2, s_set_port_line_x);
d043d8c2
MD
1107 return SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1108}
1109
360fc44c 1110SCM_PROC (s_port_column, "port-column", 1, 0, 0, scm_port_column);
1cc91f1b 1111
0f2d19dd 1112SCM
d14af9f2 1113scm_port_column (port)
0f2d19dd 1114 SCM port;
0f2d19dd 1115{
78446828 1116 port = SCM_COERCE_OUTPORT (port);
360fc44c
MD
1117 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1118 port,
1119 SCM_ARG1,
1120 s_port_column);
1121 return SCM_MAKINUM (SCM_COL (port));
0f2d19dd
JB
1122}
1123
360fc44c 1124SCM_PROC (s_set_port_column_x, "set-port-column!", 2, 0, 0, scm_set_port_column_x);
d043d8c2
MD
1125
1126SCM
1127scm_set_port_column_x (port, column)
1128 SCM port;
1129 SCM column;
1130{
360fc44c
MD
1131 port = SCM_COERCE_OUTPORT (port);
1132 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1133 port,
1134 SCM_ARG1,
1135 s_set_port_column_x);
1136 SCM_ASSERT (SCM_INUMP (column), column, SCM_ARG2, s_set_port_column_x);
d043d8c2
MD
1137 return SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1138}
1139
360fc44c 1140SCM_PROC (s_port_filename, "port-filename", 1, 0, 0, scm_port_filename);
1cc91f1b 1141
0f2d19dd 1142SCM
d14af9f2 1143scm_port_filename (port)
0f2d19dd 1144 SCM port;
0f2d19dd 1145{
78446828 1146 port = SCM_COERCE_OUTPORT (port);
360fc44c
MD
1147 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1148 port,
1149 SCM_ARG1,
1150 s_port_filename);
1151 return SCM_PTAB_ENTRY (port)->file_name;
0f2d19dd
JB
1152}
1153
360fc44c 1154SCM_PROC (s_set_port_filename_x, "set-port-filename!", 2, 0, 0, scm_set_port_filename_x);
1cc91f1b 1155
d14af9f2
MD
1156SCM
1157scm_set_port_filename_x (port, filename)
1158 SCM port;
1159 SCM filename;
d14af9f2 1160{
360fc44c
MD
1161 port = SCM_COERCE_OUTPORT (port);
1162 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
1163 port,
1164 SCM_ARG1,
1165 s_set_port_filename_x);
1166 /* We allow the user to set the filename to whatever he likes. */
d14af9f2
MD
1167 return SCM_PTAB_ENTRY (port)->file_name = filename;
1168}
1169
0f2d19dd
JB
1170#ifndef ttyname
1171extern char * ttyname();
1172#endif
1173
f12733c9
MD
1174void
1175scm_print_port_mode (SCM exp, SCM port)
1176{
1177 scm_puts (SCM_CLOSEDP (exp)
1178 ? "closed: "
1179 : (SCM_RDNG & SCM_CAR (exp)
1180 ? (SCM_WRTNG & SCM_CAR (exp)
1181 ? "input-output: "
1182 : "input: ")
1183 : (SCM_WRTNG & SCM_CAR (exp)
1184 ? "output: "
1185 : "bogus: ")),
1186 port);
1187}
1cc91f1b 1188
f12733c9
MD
1189int
1190scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 1191{
f12733c9
MD
1192 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1193 if (!type)
1194 type = "port";
b7f3516f 1195 scm_puts ("#<", port);
f12733c9 1196 scm_print_port_mode (exp, port);
b7f3516f
TT
1197 scm_puts (type, port);
1198 scm_putc (' ', port);
f12733c9 1199 scm_intprint (SCM_CDR (exp), 16, port);
b7f3516f 1200 scm_putc ('>', port);
f12733c9 1201 return 1;
0f2d19dd
JB
1202}
1203
f12733c9
MD
1204extern void scm_make_fptob ();
1205extern void scm_make_stptob ();
1206extern void scm_make_sfptob ();
1cc91f1b 1207
0f2d19dd
JB
1208void
1209scm_ports_prehistory ()
0f2d19dd
JB
1210{
1211 scm_numptob = 0;
f12733c9 1212 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
0f2d19dd
JB
1213
1214 /* WARNING: These scm_newptob calls must be done in this order.
1215 * They must agree with the port declarations in tags.h.
1216 */
f12733c9
MD
1217 /* scm_tc16_fport = */ scm_make_fptob ();
1218 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1219 /* scm_tc16_strport = */ scm_make_stptob ();
1220 /* scm_tc16_sfport = */ scm_make_sfptob ();
0f2d19dd 1221}
0f2d19dd
JB
1222
1223\f
ee149d03 1224
d68fee48 1225/* Void ports. */
0f2d19dd 1226
f12733c9 1227long scm_tc16_void_port = 0;
0f2d19dd 1228
ee149d03 1229static void
0f88a8f3 1230flush_void_port (SCM port)
0f2d19dd 1231{
3cb988bd 1232}
1cc91f1b 1233
283a1a0e 1234static void
affc96b5 1235end_input_void_port (SCM port, int offset)
283a1a0e
GH
1236{
1237}
1238
31703ab8
GH
1239static void
1240write_void_port (SCM port, void *data, size_t size)
1241{
1242}
1243
0f2d19dd
JB
1244SCM
1245scm_void_port (mode_str)
1246 char * mode_str;
0f2d19dd
JB
1247{
1248 int mode_bits;
1249 SCM answer;
840ae05d 1250 scm_port * pt;
0f2d19dd
JB
1251
1252 SCM_NEWCELL (answer);
1253 SCM_DEFER_INTS;
1254 mode_bits = scm_mode_bits (mode_str);
1255 pt = scm_add_to_port_table (answer);
0f2d19dd 1256 SCM_SETPTAB_ENTRY (answer, pt);
ee149d03
JB
1257 SCM_SETSTREAM (answer, 0);
1258 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
0f2d19dd
JB
1259 SCM_ALLOW_INTS;
1260 return answer;
1261}
1262
1263
1264SCM_PROC (s_sys_make_void_port, "%make-void-port", 1, 0, 0, scm_sys_make_void_port);
1cc91f1b 1265
0f2d19dd
JB
1266SCM
1267scm_sys_make_void_port (mode)
1268 SCM mode;
0f2d19dd 1269{
89958ad0 1270 SCM_ASSERT (SCM_NIMP (mode) && SCM_ROSTRINGP (mode), mode,
0f2d19dd
JB
1271 SCM_ARG1, s_sys_make_void_port);
1272
89958ad0 1273 SCM_COERCE_SUBSTR (mode);
0f2d19dd
JB
1274 return scm_void_port (SCM_ROCHARS (mode));
1275}
1276
0f2d19dd 1277\f
89545eba 1278/* Initialization. */
1cc91f1b 1279
0f2d19dd
JB
1280void
1281scm_init_ports ()
0f2d19dd 1282{
840ae05d
JB
1283 /* lseek() symbols. */
1284 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1285 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1286 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1287
affc96b5 1288 scm_tc16_void_port = scm_make_port_type ("void", 0, write_void_port);
0f2d19dd
JB
1289#include "ports.x"
1290}