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