* Wrapped deprecated code between #if (SCM_DEBUG_DEPRECATED == 0) #endif.
[bpt/guile.git] / libguile / fports.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
47 #include <stdio.h>
48 #include <fcntl.h>
49 #include "libguile/_scm.h"
50 #include "libguile/strings.h"
51
52 #include "libguile/validate.h"
53 #include "libguile/fports.h"
54
55 #ifdef HAVE_STRING_H
56 #include <string.h>
57 #endif
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #else
61 scm_sizet fwrite ();
62 #endif
63 #ifdef HAVE_ST_BLKSIZE
64 #include <sys/stat.h>
65 #endif
66
67 #include <errno.h>
68
69 #include "libguile/iselect.h"
70
71 /* default buffer size, used if the O/S won't supply a value. */
72 static const int default_buffer_size = 1024;
73
74 /* create FPORT buffer with specified sizes (or -1 to use default size or
75 0 for no buffer. */
76 static void
77 scm_fport_buffer_add (SCM port, int read_size, int write_size)
78 {
79 struct scm_fport *fp = SCM_FSTREAM (port);
80 scm_port *pt = SCM_PTAB_ENTRY (port);
81 char *s_scm_fport_buffer_add = "scm_fport_buffer_add";
82
83 if (read_size == -1 || write_size == -1)
84 {
85 int default_size;
86 #ifdef HAVE_ST_BLKSIZE
87 struct stat st;
88
89 default_size = (fstat (fp->fdes, &st) == -1) ? default_buffer_size
90 : st.st_blksize;
91 #else
92 default_size = default_buffer_size;
93 #endif
94 if (read_size == -1)
95 read_size = default_size;
96 if (write_size == -1)
97 write_size = default_size;
98 }
99
100 if (SCM_INPUT_PORT_P (port) && read_size > 0)
101 {
102 pt->read_buf = malloc (read_size);
103 if (pt->read_buf == NULL)
104 scm_memory_error (s_scm_fport_buffer_add);
105 pt->read_pos = pt->read_end = pt->read_buf;
106 pt->read_buf_size = read_size;
107 }
108 else
109 {
110 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
111 pt->read_buf_size = 1;
112 }
113
114 if (SCM_OUTPUT_PORT_P (port) && write_size > 0)
115 {
116 pt->write_buf = malloc (write_size);
117 if (pt->write_buf == NULL)
118 scm_memory_error (s_scm_fport_buffer_add);
119 pt->write_pos = pt->write_buf;
120 pt->write_buf_size = write_size;
121 }
122 else
123 {
124 pt->write_buf = pt->write_pos = &pt->shortbuf;
125 pt->write_buf_size = 1;
126 }
127
128 pt->write_end = pt->write_buf + pt->write_buf_size;
129 if (read_size > 0 || write_size > 0)
130 SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) & ~SCM_BUF0);
131 else
132 SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0);
133 }
134
135 SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
136 (SCM port, SCM mode, SCM size),
137 "Set the buffering mode for @var{port}. @var{mode} can be:\n"
138 "@table @code\n"
139 "@item _IONBF\n"
140 "non-buffered\n"
141 "@item _IOLBF\n"
142 "line buffered\n"
143 "@item _IOFBF\n"
144 "block buffered, using a newly allocated buffer of @var{size} bytes.\n"
145 "If @var{size} is omitted, a default size will be used.\n"
146 "@end table")
147 #define FUNC_NAME s_scm_setvbuf
148 {
149 int cmode, csize;
150 scm_port *pt;
151
152 port = SCM_COERCE_OUTPORT (port);
153
154 SCM_VALIDATE_OPFPORT (1,port);
155 SCM_VALIDATE_INUM_COPY (2,mode,cmode);
156 if (cmode != _IONBF && cmode != _IOFBF && cmode != _IOLBF)
157 scm_out_of_range (FUNC_NAME, mode);
158
159 if (cmode == _IOLBF)
160 {
161 SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUFLINE);
162 cmode = _IOFBF;
163 }
164 else
165 {
166 SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) ^ SCM_BUFLINE);
167 }
168
169 if (SCM_UNBNDP (size))
170 {
171 if (cmode == _IOFBF)
172 csize = -1;
173 else
174 csize = 0;
175 }
176 else
177 {
178 SCM_VALIDATE_INUM_COPY (3,size,csize);
179 if (csize < 0 || (cmode == _IONBF && csize > 0))
180 scm_out_of_range (FUNC_NAME, size);
181 }
182
183 pt = SCM_PTAB_ENTRY (port);
184
185 /* silently discards buffered chars. */
186 if (pt->read_buf != &pt->shortbuf)
187 scm_must_free (pt->read_buf);
188 if (pt->write_buf != &pt->shortbuf)
189 scm_must_free (pt->write_buf);
190
191 scm_fport_buffer_add (port, csize, csize);
192 return SCM_UNSPECIFIED;
193 }
194 #undef FUNC_NAME
195
196 /* Move ports with the specified file descriptor to new descriptors,
197 * reseting the revealed count to 0.
198 */
199
200 void
201 scm_evict_ports (int fd)
202 {
203 int i;
204
205 for (i = 0; i < scm_port_table_size; i++)
206 {
207 SCM port = scm_port_table[i]->port;
208
209 if (SCM_FPORTP (port))
210 {
211 struct scm_fport *fp = SCM_FSTREAM (port);
212
213 if (fp->fdes == fd)
214 {
215 fp->fdes = dup (fd);
216 if (fp->fdes == -1)
217 scm_syserror ("scm_evict_ports");
218 scm_set_port_revealed_x (port, SCM_MAKINUM (0));
219 }
220 }
221 }
222 }
223
224 /* scm_open_file
225 * Return a new port open on a given file.
226 *
227 * The mode string must match the pattern: [rwa+]** which
228 * is interpreted in the usual unix way.
229 *
230 * Return the new port.
231 */
232 SCM_DEFINE (scm_open_file, "open-file", 2, 0, 0,
233 (SCM filename, SCM modes),
234 "Open the file whose name is @var{string}, and return a port\n"
235 "representing that file. The attributes of the port are\n"
236 "determined by the @var{mode} string. The way in \n"
237 "which this is interpreted is similar to C stdio:\n\n"
238 "The first character must be one of the following:\n\n"
239 "@table @samp\n"
240 "@item r\n"
241 "Open an existing file for input.\n"
242 "@item w\n"
243 "Open a file for output, creating it if it doesn't already exist\n"
244 "or removing its contents if it does.\n"
245 "@item a\n"
246 "Open a file for output, creating it if it doesn't already exist.\n"
247 "All writes to the port will go to the end of the file.\n"
248 "The \"append mode\" can be turned off while the port is in use\n"
249 "@pxref{Ports and File Descriptors, fcntl}\n"
250 "@end table\n\n"
251 "The following additional characters can be appended:\n\n"
252 "@table @samp\n"
253 "@item +\n"
254 "Open the port for both input and output. E.g., @code{r+}: open\n"
255 "an existing file for both input and output.\n"
256 "@item 0\n"
257 "Create an \"unbuffered\" port. In this case input and output operations\n"
258 "are passed directly to the underlying port implementation without\n"
259 "additional buffering. This is likely to slow down I/O operations.\n"
260 "The buffering mode can be changed while a port is in use\n"
261 "@pxref{Ports and File Descriptors, setvbuf}\n"
262 "@item l\n"
263 "Add line-buffering to the port. The port output buffer will be\n"
264 "automatically flushed whenever a newline character is written.\n"
265 "@end table\n\n"
266 "In theory we could create read/write ports which were buffered in one\n"
267 "direction only. However this isn't included in the current interfaces.\n\n"
268 "If a file cannot be opened with the access requested,\n"
269 "@code{open-file} throws an exception.")
270 #define FUNC_NAME s_scm_open_file
271 {
272 SCM port;
273 int fdes;
274 int flags = 0;
275 char *file;
276 char *mode;
277 char *ptr;
278
279 SCM_VALIDATE_ROSTRING (1,filename);
280 SCM_VALIDATE_ROSTRING (2,modes);
281 if (SCM_SUBSTRP (filename))
282 filename = scm_makfromstr (SCM_ROCHARS (filename), SCM_ROLENGTH (filename), 0);
283 if (SCM_SUBSTRP (modes))
284 modes = scm_makfromstr (SCM_ROCHARS (modes), SCM_ROLENGTH (modes), 0);
285
286 file = SCM_ROCHARS (filename);
287 mode = SCM_ROCHARS (modes);
288
289 switch (*mode)
290 {
291 case 'r':
292 flags |= O_RDONLY;
293 break;
294 case 'w':
295 flags |= O_WRONLY | O_CREAT | O_TRUNC;
296 break;
297 case 'a':
298 flags |= O_WRONLY | O_CREAT | O_APPEND;
299 break;
300 default:
301 scm_out_of_range (FUNC_NAME, modes);
302 }
303 ptr = mode + 1;
304 while (*ptr != '\0')
305 {
306 switch (*ptr)
307 {
308 case '+':
309 flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
310 break;
311 case '0': /* unbuffered: handled later. */
312 case 'b': /* 'binary' mode: ignored. */
313 case 'l': /* line buffered: handled during output. */
314 break;
315 default:
316 scm_out_of_range (FUNC_NAME, modes);
317 }
318 ptr++;
319 }
320 SCM_SYSCALL (fdes = open (file, flags, 0666));
321 if (fdes == -1)
322 {
323 int en = errno;
324
325 SCM_SYSERROR_MSG ("~A: ~S",
326 scm_cons (scm_makfrom0str (strerror (en)),
327 scm_cons (filename, SCM_EOL)), en);
328 }
329 port = scm_fdes_to_port (fdes, mode, filename);
330 return port;
331 }
332 #undef FUNC_NAME
333
334 \f
335 /* Building Guile ports from a file descriptor. */
336
337 /* Build a Scheme port from an open file descriptor `fdes'.
338 MODE indicates whether FILE is open for reading or writing; it uses
339 the same notation as open-file's second argument.
340 NAME is a string to be used as the port's filename.
341 */
342 SCM
343 scm_fdes_to_port (int fdes, char *mode, SCM name)
344 #define FUNC_NAME "scm_fdes_to_port"
345 {
346 long mode_bits = scm_mode_bits (mode);
347 SCM port;
348 scm_port *pt;
349 int flags;
350
351 /* test that fdes is valid. */
352 flags = fcntl (fdes, F_GETFL, 0);
353 if (flags == -1)
354 SCM_SYSERROR;
355 flags &= O_ACCMODE;
356 if (flags != O_RDWR
357 && ((flags != O_WRONLY && (mode_bits & SCM_WRTNG))
358 || (flags != O_RDONLY && (mode_bits & SCM_RDNG))))
359 {
360 SCM_MISC_ERROR ("requested file mode not available on fdes", SCM_EOL);
361 }
362
363 SCM_NEWCELL (port);
364 SCM_DEFER_INTS;
365 pt = scm_add_to_port_table (port);
366 SCM_SETPTAB_ENTRY (port, pt);
367 SCM_SET_CELL_TYPE (port, (scm_tc16_fport | mode_bits));
368
369 {
370 struct scm_fport *fp
371 = (struct scm_fport *) malloc (sizeof (struct scm_fport));
372 if (fp == NULL)
373 SCM_MEMORY_ERROR;
374 fp->fdes = fdes;
375 pt->rw_random = SCM_FDES_RANDOM_P (fdes);
376 SCM_SETSTREAM (port, fp);
377 if (mode_bits & SCM_BUF0)
378 scm_fport_buffer_add (port, 0, 0);
379 else
380 scm_fport_buffer_add (port, -1, -1);
381 }
382 SCM_PTAB_ENTRY (port)->file_name = name;
383 SCM_ALLOW_INTS;
384 return port;
385 }
386 #undef FUNC_NAME
387
388 /* Return a lower bound on the number of bytes available for input. */
389 static int
390 fport_input_waiting (SCM port)
391 {
392 int fdes = SCM_FSTREAM (port)->fdes;
393
394 #ifdef HAVE_SELECT
395 struct timeval timeout;
396 SELECT_TYPE read_set;
397 SELECT_TYPE write_set;
398 SELECT_TYPE except_set;
399
400 FD_ZERO (&read_set);
401 FD_ZERO (&write_set);
402 FD_ZERO (&except_set);
403
404 FD_SET (fdes, &read_set);
405
406 timeout.tv_sec = 0;
407 timeout.tv_usec = 0;
408
409 if (select (SELECT_SET_SIZE,
410 &read_set, &write_set, &except_set, &timeout)
411 < 0)
412 scm_syserror ("fport_input_waiting");
413 return FD_ISSET (fdes, &read_set) ? 1 : 0;
414 #elif defined (FIONREAD)
415 int remir;
416 ioctl(fdes, FIONREAD, &remir);
417 return remir;
418 #else
419 scm_misc_error ("fport_input_waiting",
420 "Not fully implemented on this platform",
421 SCM_EOL);
422 #endif
423 }
424
425 \f
426 static int
427 prinfport (SCM exp,SCM port,scm_print_state *pstate)
428 {
429 scm_puts ("#<", port);
430 scm_print_port_mode (exp, port);
431 if (SCM_OPFPORTP (exp))
432 {
433 int fdes;
434 SCM name = SCM_PTAB_ENTRY (exp)->file_name;
435 scm_puts (SCM_ROSTRINGP (name)
436 ? SCM_ROCHARS (name)
437 : SCM_PTOBNAME (SCM_PTOBNUM (exp)),
438 port);
439 scm_putc (' ', port);
440 fdes = (SCM_FSTREAM (exp))->fdes;
441
442 if (isatty (fdes))
443 scm_puts (ttyname (fdes), port);
444 else
445 scm_intprint (fdes, 10, port);
446 }
447 else
448 {
449 scm_puts (SCM_PTOBNAME (SCM_PTOBNUM (exp)), port);
450 scm_putc (' ', port);
451 scm_intprint (SCM_UNPACK (SCM_CDR (exp)), 16, port);
452 }
453 scm_putc ('>', port);
454 return 1;
455 }
456
457 #ifdef GUILE_ISELECT
458 /* thread-local block for input on fport's fdes. */
459 static void
460 fport_wait_for_input (SCM port)
461 {
462 int fdes = SCM_FSTREAM (port)->fdes;
463
464 if (!fport_input_waiting (port))
465 {
466 int n;
467 SELECT_TYPE readfds;
468 int flags = fcntl (fdes, F_GETFL);
469
470 if (flags == -1)
471 scm_syserror ("scm_fdes_wait_for_input");
472 if (!(flags & O_NONBLOCK))
473 do
474 {
475 FD_ZERO (&readfds);
476 FD_SET (fdes, &readfds);
477 n = scm_internal_select (fdes + 1, &readfds, NULL, NULL, NULL);
478 }
479 while (n == -1 && errno == EINTR);
480 }
481 }
482 #endif
483
484 static void fport_flush (SCM port);
485
486 /* fill a port's read-buffer with a single read.
487 returns the first char and moves the read_pos pointer past it.
488 or returns EOF if end of file. */
489 static int
490 fport_fill_input (SCM port)
491 {
492 int count;
493 scm_port *pt = SCM_PTAB_ENTRY (port);
494 struct scm_fport *fp = SCM_FSTREAM (port);
495
496 #ifdef GUILE_ISELECT
497 fport_wait_for_input (port);
498 #endif
499 SCM_SYSCALL (count = read (fp->fdes, pt->read_buf, pt->read_buf_size));
500 if (count == -1)
501 scm_syserror ("fport_fill_input");
502 if (count == 0)
503 return EOF;
504 else
505 {
506 pt->read_pos = pt->read_buf;
507 pt->read_end = pt->read_buf + count;
508 return *pt->read_buf;
509 }
510 }
511
512 static off_t
513 fport_seek (SCM port, off_t offset, int whence)
514 {
515 scm_port *pt = SCM_PTAB_ENTRY (port);
516 struct scm_fport *fp = SCM_FSTREAM (port);
517 off_t rv;
518 off_t result;
519
520 if (pt->rw_active == SCM_PORT_WRITE)
521 {
522 if (offset != 0 || whence != SEEK_CUR)
523 {
524 fport_flush (port);
525 result = rv = lseek (fp->fdes, offset, whence);
526 }
527 else
528 {
529 /* read current position without disturbing the buffer. */
530 rv = lseek (fp->fdes, offset, whence);
531 result = rv + (pt->write_pos - pt->write_buf);
532 }
533 }
534 else if (pt->rw_active == SCM_PORT_READ)
535 {
536 if (offset != 0 || whence != SEEK_CUR)
537 {
538 /* could expand to avoid a second seek. */
539 scm_end_input (port);
540 result = rv = lseek (fp->fdes, offset, whence);
541 }
542 else
543 {
544 /* read current position without disturbing the buffer
545 (particularly the unread-char buffer). */
546 rv = lseek (fp->fdes, offset, whence);
547 result = rv - (pt->read_end - pt->read_pos);
548
549 if (pt->read_buf == pt->putback_buf)
550 result -= pt->saved_read_end - pt->saved_read_pos;
551 }
552 }
553 else /* SCM_PORT_NEITHER */
554 {
555 result = rv = lseek (fp->fdes, offset, whence);
556 }
557
558 if (rv == -1)
559 scm_syserror ("fport_seek");
560
561 return result;
562 }
563
564 static void
565 fport_truncate (SCM port, off_t length)
566 {
567 struct scm_fport *fp = SCM_FSTREAM (port);
568
569 if (ftruncate (fp->fdes, length) == -1)
570 scm_syserror ("ftruncate");
571 }
572
573 static void
574 fport_write (SCM port, const void *data, size_t size)
575 {
576 scm_port *pt = SCM_PTAB_ENTRY (port);
577
578 if (pt->write_buf == &pt->shortbuf)
579 {
580 /* "unbuffered" port. */
581 int fdes = SCM_FSTREAM (port)->fdes;
582
583 if (write (fdes, data, size) == -1)
584 scm_syserror ("fport_write");
585 }
586 else
587 {
588 const char *input = (char *) data;
589 size_t remaining = size;
590
591 while (remaining > 0)
592 {
593 int space = pt->write_end - pt->write_pos;
594 int write_len = (remaining > space) ? space : remaining;
595
596 memcpy (pt->write_pos, input, write_len);
597 pt->write_pos += write_len;
598 remaining -= write_len;
599 input += write_len;
600 if (write_len == space)
601 fport_flush (port);
602 }
603
604 /* handle line buffering. */
605 if ((SCM_UNPACK_CAR (port) & SCM_BUFLINE) && memchr (data, '\n', size))
606 fport_flush (port);
607 }
608 }
609
610 /* becomes 1 when process is exiting: normal exception handling won't
611 work by this time. */
612 extern int terminating;
613
614 static void
615 fport_flush (SCM port)
616 {
617 scm_port *pt = SCM_PTAB_ENTRY (port);
618 struct scm_fport *fp = SCM_FSTREAM (port);
619 char *ptr = pt->write_buf;
620 int init_size = pt->write_pos - pt->write_buf;
621 int remaining = init_size;
622
623 while (remaining > 0)
624 {
625 int count;
626
627 SCM_SYSCALL (count = write (fp->fdes, ptr, remaining));
628 if (count < 0)
629 {
630 /* error. assume nothing was written this call, but
631 fix up the buffer for any previous successful writes. */
632 int done = init_size - remaining;
633
634 if (done > 0)
635 {
636 int i;
637
638 for (i = 0; i < remaining; i++)
639 {
640 *(pt->write_buf + i) = *(pt->write_buf + done + i);
641 }
642 pt->write_pos = pt->write_buf + remaining;
643 }
644 if (!terminating)
645 scm_syserror ("fport_flush");
646 else
647 {
648 const char *msg = "Error: could not flush file-descriptor ";
649 char buf[11];
650
651 write (2, msg, strlen (msg));
652 sprintf (buf, "%d\n", fp->fdes);
653 write (2, buf, strlen (buf));
654
655 count = remaining;
656 }
657 }
658 ptr += count;
659 remaining -= count;
660 }
661 pt->write_pos = pt->write_buf;
662 pt->rw_active = SCM_PORT_NEITHER;
663 }
664
665 /* clear the read buffer and adjust the file position for unread bytes. */
666 static void
667 fport_end_input (SCM port, int offset)
668 {
669 struct scm_fport *fp = SCM_FSTREAM (port);
670 scm_port *pt = SCM_PTAB_ENTRY (port);
671
672 offset += pt->read_end - pt->read_pos;
673
674 if (offset > 0)
675 {
676 pt->read_pos = pt->read_end;
677 /* will throw error if unread-char used at beginning of file
678 then attempting to write. seems correct. */
679 if (lseek (fp->fdes, -offset, SEEK_CUR) == -1)
680 scm_syserror ("fport_end_input");
681 }
682 pt->rw_active = SCM_PORT_NEITHER;
683 }
684
685 static int
686 fport_close (SCM port)
687 {
688 struct scm_fport *fp = SCM_FSTREAM (port);
689 scm_port *pt = SCM_PTAB_ENTRY (port);
690 int rv;
691
692 fport_flush (port);
693 SCM_SYSCALL (rv = close (fp->fdes));
694 if (rv == -1 && errno != EBADF)
695 scm_syserror ("fport_close");
696 if (pt->read_buf == pt->putback_buf)
697 pt->read_buf = pt->saved_read_buf;
698 if (pt->read_buf != &pt->shortbuf)
699 free (pt->read_buf);
700 if (pt->write_buf != &pt->shortbuf)
701 free (pt->write_buf);
702 free ((char *) fp);
703 return rv;
704 }
705
706 static scm_sizet
707 fport_free (SCM port)
708 {
709 fport_close (port);
710 return 0;
711 }
712
713 void scm_make_fptob (void); /* Called from ports.c */
714
715 void
716 scm_make_fptob ()
717 {
718 long tc = scm_make_port_type ("file", fport_fill_input, fport_write);
719 scm_set_port_free (tc, fport_free);
720 scm_set_port_print (tc, prinfport);
721 scm_set_port_flush (tc, fport_flush);
722 scm_set_port_end_input (tc, fport_end_input);
723 scm_set_port_close (tc, fport_close);
724 scm_set_port_seek (tc, fport_seek);
725 scm_set_port_truncate (tc, fport_truncate);
726 scm_set_port_input_waiting (tc, fport_input_waiting);
727 }
728
729 void
730 scm_init_fports ()
731 {
732 #include "libguile/fports.x"
733 scm_sysintern ("_IOFBF", SCM_MAKINUM (_IOFBF));
734 scm_sysintern ("_IOLBF", SCM_MAKINUM (_IOLBF));
735 scm_sysintern ("_IONBF", SCM_MAKINUM (_IONBF));
736 }
737
738 /*
739 Local Variables:
740 c-file-style: "gnu"
741 End:
742 */