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