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