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