* *.[hc]: add Emacs magic at the end of file, to ensure GNU
[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_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.Close all open file ports used by the interpreter\n"
644 "except for those supplied as arguments. This procedure\n"
645 "is intended to be used before an exec call to close file descriptors\n"
646 "which are not needed in the new process.")
647 #define FUNC_NAME s_scm_close_all_ports_except
648 {
649 int i = 0;
650 SCM_VALIDATE_CONS (1,ports);
651 while (i < scm_port_table_size)
652 {
653 SCM thisport = scm_port_table[i]->port;
654 int found = 0;
655 SCM ports_ptr = ports;
656
657 while (SCM_NNULLP (ports_ptr))
658 {
659 SCM port = SCM_COERCE_OUTPORT (SCM_CAR (ports_ptr));
660 if (i == 0)
661 SCM_VALIDATE_OPPORT (SCM_ARG1,port);
662 if (port == thisport)
663 found = 1;
664 ports_ptr = SCM_CDR (ports_ptr);
665 }
666 if (found)
667 i++;
668 else
669 /* i is not to be incremented here. */
670 scm_close_port (thisport);
671 }
672 return SCM_UNSPECIFIED;
673 }
674 #undef FUNC_NAME
675
676
677 \f
678 /* Utter miscellany. Gosh, we should clean this up some time. */
679
680 SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
681 (SCM x),
682 "Returns @code{#t} if @var{x} is an input port, otherwise returns\n"
683 "@code{#f}. Any object satisfying this predicate also satisfies\n"
684 "@code{port?}.")
685 #define FUNC_NAME s_scm_input_port_p
686 {
687 if (SCM_IMP (x))
688 return SCM_BOOL_F;
689 return SCM_BOOL(SCM_INPORTP (x));
690 }
691 #undef FUNC_NAME
692
693 SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
694 (SCM x),
695 "Returns @code{#t} if @var{x} is an output port, otherwise returns\n"
696 "@code{#f}. Any object satisfying this predicate also satisfies\n"
697 "@code{port?}.")
698 #define FUNC_NAME s_scm_output_port_p
699 {
700 if (SCM_IMP (x))
701 return SCM_BOOL_F;
702 if (SCM_PORT_WITH_PS_P (x))
703 x = SCM_PORT_WITH_PS_PORT (x);
704 return SCM_BOOL(SCM_OUTPORTP (x));
705 }
706 #undef FUNC_NAME
707
708 SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
709 (SCM port),
710 "Returns @code{#t} if @var{port} is closed or @code{#f} if it is open.")
711 #define FUNC_NAME s_scm_port_closed_p
712 {
713 SCM_VALIDATE_PORT (1,port);
714 return SCM_NEGATE_BOOL(SCM_OPPORTP (port));
715 }
716 #undef FUNC_NAME
717
718 SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
719 (SCM x),
720 "Returns @code{#t} if @var{x} is an end-of-file object; otherwise\n"
721 "returns @code{#f}.")
722 #define FUNC_NAME s_scm_eof_object_p
723 {
724 return SCM_BOOL(SCM_EOF_OBJECT_P (x));
725 }
726 #undef FUNC_NAME
727
728 SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
729 (SCM port),
730 "Flush the specified output port, or the current output port if @var{port}\n"
731 "is omitted. The current output buffer contents are passed to the \n"
732 "underlying port implementation (e.g., in the case of fports, the\n"
733 "data will be written to the file and the output buffer will be cleared.)\n"
734 "It has no effect on an unbuffered port.\n\n"
735 "The return value is unspecified.")
736 #define FUNC_NAME s_scm_force_output
737 {
738 if (SCM_UNBNDP (port))
739 port = scm_cur_outp;
740 else
741 {
742 port = SCM_COERCE_OUTPORT (port);
743 SCM_VALIDATE_OPOUTPORT (1,port);
744 }
745 scm_flush (port);
746 return SCM_UNSPECIFIED;
747 }
748 #undef FUNC_NAME
749
750 SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
751 (),
752 "Equivalent to calling @code{force-output} on\n"
753 "all open output ports. The return value is unspecified.")
754 #define FUNC_NAME s_scm_flush_all_ports
755 {
756 int i;
757
758 for (i = 0; i < scm_port_table_size; i++)
759 {
760 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
761 scm_flush (scm_port_table[i]->port);
762 }
763 return SCM_UNSPECIFIED;
764 }
765 #undef FUNC_NAME
766
767 SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
768 (SCM port),
769 "Returns the next character available from @var{port}, updating\n"
770 "@var{port} to point to the following character. If no more\n"
771 "characters are available, an end-of-file object is returned.")
772 #define FUNC_NAME s_scm_read_char
773 {
774 int c;
775 if (SCM_UNBNDP (port))
776 port = scm_cur_inp;
777 SCM_VALIDATE_OPINPORT (1,port);
778 c = scm_getc (port);
779 if (EOF == c)
780 return SCM_EOF_VAL;
781 return SCM_MAKE_CHAR (c);
782 }
783 #undef FUNC_NAME
784
785 /* this should only be called when the read buffer is empty. it
786 tries to refill the read buffer. it returns the first char from
787 the port, which is either EOF or *(pt->read_pos). */
788 int
789 scm_fill_input (SCM port)
790 {
791 scm_port *pt = SCM_PTAB_ENTRY (port);
792
793 if (pt->read_buf == pt->putback_buf)
794 {
795 /* finished reading put-back chars. */
796 pt->read_buf = pt->saved_read_buf;
797 pt->read_pos = pt->saved_read_pos;
798 pt->read_end = pt->saved_read_end;
799 pt->read_buf_size = pt->saved_read_buf_size;
800 if (pt->read_pos < pt->read_end)
801 return *(pt->read_pos);
802 }
803 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
804 }
805
806 int
807 scm_getc (SCM port)
808 {
809 int c;
810 scm_port *pt = SCM_PTAB_ENTRY (port);
811
812 if (pt->rw_active == SCM_PORT_WRITE)
813 {
814 /* may be marginally faster than calling scm_flush. */
815 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
816 }
817
818 if (pt->rw_random)
819 pt->rw_active = SCM_PORT_READ;
820
821 if (pt->read_pos >= pt->read_end)
822 {
823 if (scm_fill_input (port) == EOF)
824 return EOF;
825 }
826
827 c = *(pt->read_pos++);
828
829 if (c == '\n')
830 {
831 SCM_INCLINE (port);
832 }
833 else if (c == '\t')
834 {
835 SCM_TABCOL (port);
836 }
837 else
838 {
839 SCM_INCCOL (port);
840 }
841
842 return c;
843 }
844
845 void
846 scm_putc (char c, SCM port)
847 {
848 scm_lfwrite (&c, 1, port);
849 }
850
851 void
852 scm_puts (const char *s, SCM port)
853 {
854 scm_lfwrite (s, strlen (s), port);
855 }
856
857 void
858 scm_lfwrite (const char *ptr, scm_sizet size, SCM port)
859 {
860 scm_port *pt = SCM_PTAB_ENTRY (port);
861 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
862
863 if (pt->rw_active == SCM_PORT_READ)
864 scm_end_input (port);
865
866 ptob->write (port, ptr, size);
867
868 if (pt->rw_random)
869 pt->rw_active = SCM_PORT_WRITE;
870 }
871
872
873 void
874 scm_flush (SCM port)
875 {
876 scm_sizet i = SCM_PTOBNUM (port);
877 (scm_ptobs[i].flush) (port);
878 }
879
880 void
881 scm_end_input (SCM port)
882 {
883 int offset;
884 scm_port *pt = SCM_PTAB_ENTRY (port);
885
886 if (pt->read_buf == pt->putback_buf)
887 {
888 offset = pt->read_end - pt->read_pos;
889 pt->read_buf = pt->saved_read_buf;
890 pt->read_pos = pt->saved_read_pos;
891 pt->read_end = pt->saved_read_end;
892 pt->read_buf_size = pt->saved_read_buf_size;
893 }
894 else
895 offset = 0;
896
897 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
898 }
899
900 \f
901
902
903 void
904 scm_ungetc (int c, SCM port)
905 {
906 scm_port *pt = SCM_PTAB_ENTRY (port);
907
908 if (pt->read_buf == pt->putback_buf)
909 /* already using the put-back buffer. */
910 {
911 /* enlarge putback_buf if necessary. */
912 if (pt->read_end == pt->read_buf + pt->read_buf_size
913 && pt->read_buf == pt->read_pos)
914 {
915 int new_size = pt->read_buf_size * 2;
916 unsigned char *tmp =
917 (unsigned char *) realloc (pt->putback_buf, new_size);
918
919 if (tmp == NULL)
920 scm_memory_error ("scm_ungetc");
921 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
922 pt->read_end = pt->read_buf + pt->read_buf_size;
923 pt->read_buf_size = pt->putback_buf_size = new_size;
924 }
925
926 /* shift any existing bytes to buffer + 1. */
927 if (pt->read_pos == pt->read_end)
928 pt->read_end = pt->read_buf + 1;
929 else if (pt->read_pos != pt->read_buf + 1)
930 {
931 int count = pt->read_end - pt->read_pos;
932
933 memmove (pt->read_buf + 1, pt->read_pos, count);
934 pt->read_end = pt->read_buf + 1 + count;
935 }
936
937 pt->read_pos = pt->read_buf;
938 }
939 else
940 /* switch to the put-back buffer. */
941 {
942 if (pt->putback_buf == NULL)
943 {
944 pt->putback_buf = (char *) malloc (SCM_INITIAL_PUTBACK_BUF_SIZE);
945 if (pt->putback_buf == NULL)
946 scm_memory_error ("scm_ungetc");
947 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
948 }
949
950 pt->saved_read_buf = pt->read_buf;
951 pt->saved_read_pos = pt->read_pos;
952 pt->saved_read_end = pt->read_end;
953 pt->saved_read_buf_size = pt->read_buf_size;
954
955 pt->read_pos = pt->read_buf = pt->putback_buf;
956 pt->read_end = pt->read_buf + 1;
957 pt->read_buf_size = pt->putback_buf_size;
958 }
959
960 *pt->read_buf = c;
961
962 if (pt->rw_random)
963 pt->rw_active = SCM_PORT_READ;
964
965 if (c == '\n')
966 {
967 /* What should col be in this case?
968 * We'll leave it at -1.
969 */
970 SCM_LINUM (port) -= 1;
971 }
972 else
973 SCM_COL(port) -= 1;
974 }
975
976
977 void
978 scm_ungets (const char *s, int n, SCM port)
979 {
980 /* This is simple minded and inefficient, but unreading strings is
981 * probably not a common operation, and remember that line and
982 * column numbers have to be handled...
983 *
984 * Please feel free to write an optimized version!
985 */
986 while (n--)
987 scm_ungetc (s[n], port);
988 }
989
990
991 SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
992 (SCM port),
993 "Returns the next character available from @var{port},\n"
994 "@emph{without} updating @var{port} to point to the following\n"
995 "character. If no more characters are available, an end-of-file object\n"
996 "is returned.@footnote{The value returned by a call to @code{peek-char}\n"
997 "is the same as the value that would have been returned by a call to\n"
998 "@code{read-char} on the same port. The only difference is that the very\n"
999 "next call to @code{read-char} or @code{peek-char} on that\n"
1000 "@var{port} will return the value returned by the preceding call to\n"
1001 "@code{peek-char}. In particular, a call to @code{peek-char} on an\n"
1002 "interactive port will hang waiting for input whenever a call to\n"
1003 "@code{read-char} would have hung.}")
1004 #define FUNC_NAME s_scm_peek_char
1005 {
1006 int c;
1007 if (SCM_UNBNDP (port))
1008 port = scm_cur_inp;
1009 else
1010 SCM_VALIDATE_OPINPORT (1,port);
1011 c = scm_getc (port);
1012 if (EOF == c)
1013 return SCM_EOF_VAL;
1014 scm_ungetc (c, port);
1015 return SCM_MAKE_CHAR (c);
1016 }
1017 #undef FUNC_NAME
1018
1019 SCM_DEFINE (scm_unread_char, "unread-char", 2, 0, 0,
1020 (SCM cobj, SCM port),
1021 "Place @var{char} in @var{port} so that it will be read by the\n"
1022 "next read operation. If called multiple times, the unread characters\n"
1023 "will be read again in last-in first-out order. If @var{port} is\n"
1024 "not supplied, the current input port is used.")
1025 #define FUNC_NAME s_scm_unread_char
1026 {
1027 int c;
1028
1029 SCM_VALIDATE_CHAR (1,cobj);
1030 if (SCM_UNBNDP (port))
1031 port = scm_cur_inp;
1032 else
1033 SCM_VALIDATE_OPINPORT (2,port);
1034
1035 c = SCM_CHAR (cobj);
1036
1037 scm_ungetc (c, port);
1038 return cobj;
1039 }
1040 #undef FUNC_NAME
1041
1042 SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1043 (SCM str, SCM port),
1044 "Place the string @var{str} in @var{port} so that its characters will be\n"
1045 "read in subsequent read operations. If called multiple times, the\n"
1046 "unread characters will be read again in last-in first-out order. If\n"
1047 "@var{port} is not supplied, the current-input-port is used.")
1048 #define FUNC_NAME s_scm_unread_string
1049 {
1050 SCM_VALIDATE_STRING (1,str);
1051 if (SCM_UNBNDP (port))
1052 port = scm_cur_inp;
1053 else
1054 SCM_VALIDATE_OPINPORT (2,port);
1055
1056 scm_ungets (SCM_ROUCHARS (str), SCM_LENGTH (str), port);
1057
1058 return str;
1059 }
1060 #undef FUNC_NAME
1061
1062 SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1063 (SCM object, SCM offset, SCM whence),
1064 "Sets the current position of @var{fd/port} to the integer @var{offset},\n"
1065 "which is interpreted according to the value of @var{whence}.\n\n"
1066 "One of the following variables should be supplied\n"
1067 "for @var{whence}:\n"
1068 "@defvar SEEK_SET\n"
1069 "Seek from the beginning of the file.\n"
1070 "@end defvar\n"
1071 "@defvar SEEK_CUR\n"
1072 "Seek from the current position.\n"
1073 "@end defvar\n"
1074 "@defvar SEEK_END\n"
1075 "Seek from the end of the file.\n"
1076 "@end defvar\n\n"
1077 "If @var{fd/port} is a file descriptor, the underlying system call is\n"
1078 "@code{lseek}. @var{port} may be a string port.\n\n"
1079 "The value returned is the new position in the file. This means that\n"
1080 "the current position of a port can be obtained using:\n"
1081 "@smalllisp\n"
1082 "(seek port 0 SEEK_CUR)\n"
1083 "@end smalllisp")
1084 #define FUNC_NAME s_scm_seek
1085 {
1086 off_t off;
1087 off_t rv;
1088 int how;
1089
1090 object = SCM_COERCE_OUTPORT (object);
1091
1092 off = SCM_NUM2LONG (2,offset);
1093 SCM_VALIDATE_INUM_COPY (3,whence,how);
1094 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1095 SCM_OUT_OF_RANGE (3, whence);
1096 if (SCM_OPPORTP (object))
1097 {
1098 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
1099
1100 if (!ptob->seek)
1101 SCM_MISC_ERROR ("port is not seekable",
1102 scm_cons (object, SCM_EOL));
1103 else
1104 rv = ptob->seek (object, off, how);
1105 }
1106 else /* file descriptor?. */
1107 {
1108 SCM_VALIDATE_INUM (1,object);
1109 rv = lseek (SCM_INUM (object), off, how);
1110 if (rv == -1)
1111 SCM_SYSERROR;
1112 }
1113 return scm_long2num (rv);
1114 }
1115 #undef FUNC_NAME
1116
1117 SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1118 (SCM object, SCM length),
1119 "Truncates the object referred to by @var{obj} to at most @var{size} bytes.\n"
1120 "@var{obj} can be a string containing a file name or an integer file\n"
1121 "descriptor or a port. @var{size} may be omitted if @var{obj} is not\n"
1122 "a file name, in which case the truncation occurs at the current port.\n"
1123 "position.\n\n"
1124 "The return value is unspecified.")
1125 #define FUNC_NAME s_scm_truncate_file
1126 {
1127 int rv;
1128 off_t c_length;
1129
1130 /* object can be a port, fdes or filename. */
1131
1132 if (SCM_UNBNDP (length))
1133 {
1134 /* must supply length if object is a filename. */
1135 if (SCM_ROSTRINGP (object))
1136 SCM_MISC_ERROR("must supply length if OBJECT is a filename",SCM_EOL);
1137
1138 length = scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
1139 }
1140 c_length = SCM_NUM2LONG (2,length);
1141 if (c_length < 0)
1142 SCM_MISC_ERROR ("negative offset", SCM_EOL);
1143
1144 object = SCM_COERCE_OUTPORT (object);
1145 if (SCM_INUMP (object))
1146 {
1147 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1148 }
1149 else if (SCM_OPOUTPORTP (object))
1150 {
1151 scm_port *pt = SCM_PTAB_ENTRY (object);
1152 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
1153
1154 if (!ptob->truncate)
1155 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
1156 if (pt->rw_active == SCM_PORT_READ)
1157 scm_end_input (object);
1158 else if (pt->rw_active == SCM_PORT_WRITE)
1159 ptob->flush (object);
1160
1161 ptob->truncate (object, c_length);
1162 rv = 0;
1163 }
1164 else
1165 {
1166 SCM_VALIDATE_ROSTRING (1,object);
1167 SCM_COERCE_SUBSTR (object);
1168 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), c_length));
1169 }
1170 if (rv == -1)
1171 SCM_SYSERROR;
1172 return SCM_UNSPECIFIED;
1173 }
1174 #undef FUNC_NAME
1175
1176 SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1177 (SCM port),
1178 "Return the current line number for PORT.")
1179 #define FUNC_NAME s_scm_port_line
1180 {
1181 port = SCM_COERCE_OUTPORT (port);
1182 SCM_VALIDATE_OPENPORT (1,port);
1183 return SCM_MAKINUM (SCM_LINUM (port));
1184 }
1185 #undef FUNC_NAME
1186
1187 SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1188 (SCM port, SCM line),
1189 "Set the current line number for PORT to LINE.")
1190 #define FUNC_NAME s_scm_set_port_line_x
1191 {
1192 port = SCM_COERCE_OUTPORT (port);
1193 SCM_VALIDATE_OPENPORT (1,port);
1194 SCM_VALIDATE_INUM (2,line);
1195 SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1196 return SCM_UNSPECIFIED;
1197 }
1198 #undef FUNC_NAME
1199
1200 SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1201 (SCM port),
1202 "@deffnx primitive port-line [input-port]\n"
1203 "Return the current column number or line number of @var{input-port},\n"
1204 "using the current input port if none is specified. If the number is\n"
1205 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1206 "- i.e. the first character of the first line is line 0, column 0.\n"
1207 "(However, when you display a file position, for example in an error\n"
1208 "message, we recommand you add 1 to get 1-origin integers. This is\n"
1209 "because lines and column numbers traditionally start with 1, and that is\n"
1210 "what non-programmers will find most natural.)")
1211 #define FUNC_NAME s_scm_port_column
1212 {
1213 port = SCM_COERCE_OUTPORT (port);
1214 SCM_VALIDATE_OPENPORT (1,port);
1215 return SCM_MAKINUM (SCM_COL (port));
1216 }
1217 #undef FUNC_NAME
1218
1219 SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1220 (SCM port, SCM column),
1221 "@deffnx primitive set-port-column! [input-port] column\n"
1222 "Set the current column or line number of @var{input-port}, using the\n"
1223 "current input port if none is specified.")
1224 #define FUNC_NAME s_scm_set_port_column_x
1225 {
1226 port = SCM_COERCE_OUTPORT (port);
1227 SCM_VALIDATE_OPENPORT (1,port);
1228 SCM_VALIDATE_INUM (2,column);
1229 SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1230 return SCM_UNSPECIFIED;
1231 }
1232 #undef FUNC_NAME
1233
1234 SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1235 (SCM port),
1236 "Return the filename associated with @var{port}. This function returns\n"
1237 "the strings \"standard input\", \"standard output\" and \"standard error\""
1238 "when called on the current input, output and error ports respectively.")
1239 #define FUNC_NAME s_scm_port_filename
1240 {
1241 port = SCM_COERCE_OUTPORT (port);
1242 SCM_VALIDATE_OPENPORT (1,port);
1243 return SCM_PTAB_ENTRY (port)->file_name;
1244 }
1245 #undef FUNC_NAME
1246
1247 SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1248 (SCM port, SCM filename),
1249 "Change the filename associated with @var{port}, using the current input\n"
1250 "port if none is specified. Note that this does not change the port's\n"
1251 "source of data, but only the value that is returned by\n"
1252 "@code{port-filename} and reported in diagnostic output.")
1253 #define FUNC_NAME s_scm_set_port_filename_x
1254 {
1255 port = SCM_COERCE_OUTPORT (port);
1256 SCM_VALIDATE_OPENPORT (1,port);
1257 /* We allow the user to set the filename to whatever he likes. */
1258 return SCM_PTAB_ENTRY (port)->file_name = filename;
1259 }
1260 #undef FUNC_NAME
1261
1262 #ifndef ttyname
1263 extern char * ttyname();
1264 #endif
1265
1266 void
1267 scm_print_port_mode (SCM exp, SCM port)
1268 {
1269 scm_puts (SCM_CLOSEDP (exp)
1270 ? "closed: "
1271 : (SCM_RDNG & SCM_UNPACK_CAR (exp)
1272 ? (SCM_WRTNG & SCM_UNPACK_CAR (exp)
1273 ? "input-output: "
1274 : "input: ")
1275 : (SCM_WRTNG & SCM_UNPACK_CAR (exp)
1276 ? "output: "
1277 : "bogus: ")),
1278 port);
1279 }
1280
1281 int
1282 scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
1283 {
1284 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1285 if (!type)
1286 type = "port";
1287 scm_puts ("#<", port);
1288 scm_print_port_mode (exp, port);
1289 scm_puts (type, port);
1290 scm_putc (' ', port);
1291 scm_intprint ((int) SCM_CDR (exp), 16, port);
1292 scm_putc ('>', port);
1293 return 1;
1294 }
1295
1296 extern void scm_make_fptob ();
1297 extern void scm_make_stptob ();
1298 extern void scm_make_sfptob ();
1299
1300 void
1301 scm_ports_prehistory ()
1302 {
1303 scm_numptob = 0;
1304 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
1305
1306 /* WARNING: These scm_newptob calls must be done in this order.
1307 * They must agree with the port declarations in tags.h.
1308 */
1309 /* scm_tc16_fport = */ scm_make_fptob ();
1310 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1311 /* scm_tc16_strport = */ scm_make_stptob ();
1312 /* scm_tc16_sfport = */ scm_make_sfptob ();
1313 }
1314
1315 \f
1316
1317 /* Void ports. */
1318
1319 long scm_tc16_void_port = 0;
1320
1321 static int fill_input_void_port (SCM port)
1322 {
1323 return EOF;
1324 }
1325
1326 static void
1327 write_void_port (SCM port, const void *data, size_t size)
1328 {
1329 }
1330
1331 SCM
1332 scm_void_port (char *mode_str)
1333 {
1334 int mode_bits;
1335 SCM answer;
1336 scm_port * pt;
1337
1338 SCM_NEWCELL (answer);
1339 SCM_DEFER_INTS;
1340 mode_bits = scm_mode_bits (mode_str);
1341 pt = scm_add_to_port_table (answer);
1342 scm_port_non_buffer (pt);
1343 SCM_SETPTAB_ENTRY (answer, pt);
1344 SCM_SETSTREAM (answer, 0);
1345 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
1346 SCM_ALLOW_INTS;
1347 return answer;
1348 }
1349
1350 SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1351 (SCM mode),
1352 "Create and return a new void port. A void port acts like\n"
1353 "/dev/null. The @var{mode} argument\n"
1354 "specifies the input/output modes for this port: see the\n"
1355 "documentation for @code{open-file} in @ref{File Ports}.")
1356 #define FUNC_NAME s_scm_sys_make_void_port
1357 {
1358 SCM_VALIDATE_ROSTRING (1,mode);
1359 SCM_COERCE_SUBSTR (mode);
1360 return scm_void_port (SCM_ROCHARS (mode));
1361 }
1362 #undef FUNC_NAME
1363
1364 \f
1365 /* Initialization. */
1366
1367 void
1368 scm_init_ports ()
1369 {
1370 /* lseek() symbols. */
1371 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1372 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1373 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1374
1375 scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port,
1376 write_void_port);
1377 #include "ports.x"
1378 }
1379
1380 /*
1381 Local Variables:
1382 c-file-style: "gnu"
1383 End:
1384 */