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