1 /* Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
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)
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.
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
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
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.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
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.
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. */
57 #ifdef HAVE_ST_BLKSIZE
65 /* create FPORT buffer with specified sizes (or -1 to use default size or
68 scm_fport_buffer_add (SCM port
, int read_size
, int write_size
)
70 struct scm_fport
*fp
= SCM_FSTREAM (port
);
71 scm_port
*pt
= SCM_PTAB_ENTRY (port
);
72 char *s_scm_fport_buffer_add
= "scm_fport_buffer_add";
74 if (read_size
== -1 || write_size
== -1)
77 #ifdef HAVE_ST_BLKSIZE
80 if (fstat (fp
->fdes
, &st
) == -1)
81 scm_syserror (s_scm_fport_buffer_add
);
82 default_size
= st
.st_blksize
;
87 read_size
= default_size
;
89 write_size
= default_size
;
92 if (SCM_INPORTP (port
) && read_size
> 0)
94 pt
->read_buf
= malloc (read_size
);
95 if (pt
->read_buf
== NULL
)
96 scm_memory_error (s_scm_fport_buffer_add
);
97 pt
->read_pos
= pt
->read_end
= pt
->read_buf
;
98 pt
->read_buf_size
= read_size
;
102 pt
->read_pos
= pt
->read_buf
= pt
->read_end
= &pt
->shortbuf
;
103 pt
->read_buf_size
= 1;
106 if (SCM_OUTPORTP (port
) && write_size
> 0)
108 pt
->write_buf
= malloc (write_size
);
109 if (pt
->write_buf
== NULL
)
110 scm_memory_error (s_scm_fport_buffer_add
);
111 pt
->write_pos
= pt
->write_buf
;
112 pt
->write_buf_size
= write_size
;
116 pt
->write_buf
= pt
->write_pos
= &pt
->shortbuf
;
117 pt
->write_buf_size
= 1;
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
);
124 SCM_SETCAR (port
, (SCM_CAR (port
) | SCM_BUF0
));
127 SCM_PROC (s_setvbuf
, "setvbuf", 2, 1, 0, scm_setvbuf
);
129 scm_setvbuf (SCM port
, SCM mode
, SCM size
)
134 port
= SCM_COERCE_OUTPORT (port
);
136 SCM_ASSERT (SCM_NIMP (port
) && SCM_OPFPORTP (port
), port
, SCM_ARG1
,
138 SCM_ASSERT (SCM_INUMP (mode
), mode
, SCM_ARG2
, s_setvbuf
);
139 cmode
= SCM_INUM (mode
);
140 if (cmode
!= _IONBF
&& cmode
!= _IOFBF
)
141 scm_out_of_range (s_setvbuf
, mode
);
142 if (SCM_UNBNDP (size
))
151 SCM_ASSERT (SCM_INUMP (size
), size
, SCM_ARG3
, s_setvbuf
);
152 csize
= SCM_INUM (size
);
153 if (csize
< 0 || (cmode
== _IONBF
&& csize
> 0))
154 scm_out_of_range (s_setvbuf
, size
);
156 pt
= SCM_PTAB_ENTRY (port
);
158 /* silently discards buffered chars. */
159 if (pt
->read_buf
!= &pt
->shortbuf
)
160 scm_must_free (pt
->read_buf
);
161 if (pt
->write_buf
!= &pt
->shortbuf
)
162 scm_must_free (pt
->write_buf
);
164 scm_fport_buffer_add (port
, csize
, csize
);
165 return SCM_UNSPECIFIED
;
168 /* Move ports with the specified file descriptor to new descriptors,
169 * reseting the revealed count to 0.
178 for (i
= 0; i
< scm_port_table_size
; i
++)
180 SCM port
= scm_port_table
[i
]->port
;
182 if (SCM_FPORTP (port
))
184 struct scm_fport
*fp
= SCM_FSTREAM (port
);
190 scm_syserror ("scm_evict_ports");
191 scm_set_port_revealed_x (port
, SCM_MAKINUM (0));
198 * Return a new port open on a given file.
200 * The mode string must match the pattern: [rwa+]** which
201 * is interpreted in the usual unix way.
203 * Return the new port.
205 SCM_PROC(s_open_file
, "open-file", 2, 0, 0, scm_open_file
);
208 scm_open_file (filename
, modes
)
219 SCM_ASSERT (SCM_NIMP (filename
) && SCM_ROSTRINGP (filename
), filename
, SCM_ARG1
, s_open_file
);
220 SCM_ASSERT (SCM_NIMP (modes
) && SCM_ROSTRINGP (modes
), modes
, SCM_ARG2
, s_open_file
);
221 if (SCM_SUBSTRP (filename
))
222 filename
= scm_makfromstr (SCM_ROCHARS (filename
), SCM_ROLENGTH (filename
), 0);
223 if (SCM_SUBSTRP (modes
))
224 modes
= scm_makfromstr (SCM_ROCHARS (modes
), SCM_ROLENGTH (modes
), 0);
226 file
= SCM_ROCHARS (filename
);
227 mode
= SCM_ROCHARS (modes
);
235 flags
|= O_WRONLY
| O_CREAT
| O_TRUNC
;
238 flags
|= O_WRONLY
| O_CREAT
| O_APPEND
;
241 scm_out_of_range (s_open_file
, modes
);
249 flags
= (flags
& ~(O_RDONLY
| O_WRONLY
)) | O_RDWR
;
251 case '0': /* unbuffered: handled later. */
252 case 'b': /* 'binary' mode: ignored. */
255 scm_out_of_range (s_open_file
, modes
);
259 SCM_SYSCALL (fdes
= open (file
, flags
, 0666));
264 scm_syserror_msg (s_open_file
, "%s: %S",
265 scm_cons (scm_makfrom0str (strerror (en
)),
266 scm_cons (filename
, SCM_EOL
)),
269 port
= scm_fdes_to_port (fdes
, mode
, filename
);
274 /* Building Guile ports from a file descriptor. */
276 /* Build a Scheme port from an open file descriptor `fdes'.
277 MODE indicates whether FILE is open for reading or writing; it uses
278 the same notation as open-file's second argument.
279 Use NAME as the port's filename. */
282 scm_fdes_to_port (int fdes
, char *mode
, SCM name
)
284 long mode_bits
= scm_mode_bits (mode
);
290 pt
= scm_add_to_port_table (port
);
291 SCM_SETPTAB_ENTRY (port
, pt
);
292 SCM_SETCAR (port
, (scm_tc16_fport
| mode_bits
));
296 = (struct scm_fport
*) malloc (sizeof (struct scm_fport
));
298 scm_memory_error ("scm_fdes_to_port");
300 pt
->rw_random
= (mode_bits
& SCM_RDNG
) && (mode_bits
& SCM_WRTNG
)
301 && SCM_FDES_RANDOM_P (fdes
);
302 SCM_SETSTREAM (port
, fp
);
303 if (mode_bits
& SCM_BUF0
)
304 scm_fport_buffer_add (port
, 0, 0);
306 scm_fport_buffer_add (port
, -1, -1);
308 SCM_PTAB_ENTRY (port
)->file_name
= name
;
314 /* Check whether an fport's fdes can supply input. */
316 fport_input_waiting_p (SCM port
)
318 int fdes
= SCM_FSTREAM (port
)->fdes
;
321 struct timeval timeout
;
322 SELECT_TYPE read_set
;
323 SELECT_TYPE write_set
;
324 SELECT_TYPE except_set
;
327 FD_ZERO (&write_set
);
328 FD_ZERO (&except_set
);
330 FD_SET (fdes
, &read_set
);
335 if (select (SELECT_SET_SIZE
,
336 &read_set
, &write_set
, &except_set
, &timeout
)
338 scm_syserror ("fport_input_waiting_p");
339 return FD_ISSET (fdes
, &read_set
);
340 #elif defined (FIONREAD)
342 ioctl(fdes
, FIONREAD
, &remir
);
345 scm_misc_error ("fport_input_waiting_p",
346 "Not fully implemented on this platform",
352 static int prinfport
SCM_P ((SCM exp
, SCM port
, scm_print_state
*pstate
));
355 prinfport (exp
, port
, pstate
)
358 scm_print_state
*pstate
;
360 scm_puts ("#<", port
);
361 scm_print_port_mode (exp
, port
);
362 if (SCM_OPFPORTP (exp
))
365 SCM name
= SCM_PTAB_ENTRY (exp
)->file_name
;
366 scm_puts (SCM_NIMP (name
) && SCM_ROSTRINGP (name
)
368 : SCM_PTOBNAME (SCM_PTOBNUM (exp
)),
370 scm_putc (' ', port
);
371 fdes
= (SCM_FSTREAM (exp
))->fdes
;
374 scm_puts (ttyname (fdes
), port
);
376 scm_intprint (fdes
, 10, port
);
380 scm_puts (SCM_PTOBNAME (SCM_PTOBNUM (exp
)), port
);
381 scm_putc (' ', port
);
382 scm_intprint (SCM_CDR (exp
), 16, port
);
384 scm_putc ('>', port
);
389 /* thread-local block for input on fport's fdes. */
391 fport_wait_for_input (SCM port
)
393 int fdes
= SCM_FSTREAM (port
)->fdes
;
395 if (!fport_input_waiting_p (port
))
399 int flags
= fcntl (fdes
, F_GETFL
);
402 scm_syserror ("scm_fdes_wait_for_input");
403 if (!(flags
& O_NONBLOCK
))
407 FD_SET (fdes
, &readfds
);
408 n
= scm_internal_select (fdes
+ 1, &readfds
, NULL
, NULL
, NULL
);
410 while (n
== -1 && errno
== EINTR
);
415 static void local_fflush (SCM port
);
417 /* fill a port's read-buffer with a single read.
418 returns the first char and moves the read_pos pointer past it.
419 or returns EOF if end of file. */
421 fport_fill_buffer (SCM port
)
424 scm_port
*pt
= SCM_PTAB_ENTRY (port
);
425 struct scm_fport
*fp
= SCM_FSTREAM (port
);
428 fport_wait_for_input (port
);
430 SCM_SYSCALL (count
= read (fp
->fdes
, pt
->read_buf
, pt
->read_buf_size
));
432 scm_syserror ("fport_fill_buffer");
437 pt
->read_pos
= pt
->read_buf
;
438 pt
->read_end
= pt
->read_buf
+ count
;
439 return *pt
->read_buf
;
444 local_seek (SCM port
, off_t offset
, int whence
)
446 struct scm_fport
*fp
= SCM_FSTREAM (port
);
447 off_t result
= lseek (fp
->fdes
, offset
, whence
);
450 scm_syserror ("local_seek");
455 local_ftruncate (SCM port
, off_t length
)
457 struct scm_fport
*fp
= SCM_FSTREAM (port
);
459 if (ftruncate (fp
->fdes
, length
) == -1)
460 scm_syserror ("ftruncate");
463 /* becomes 1 when process is exiting: exception handling is disabled. */
464 extern int terminating
;
467 local_fflush (SCM port
)
469 scm_port
*pt
= SCM_PTAB_ENTRY (port
);
470 struct scm_fport
*fp
= SCM_FSTREAM (port
);
471 char *ptr
= pt
->write_buf
;
472 int init_size
= pt
->write_pos
- pt
->write_buf
;
473 int remaining
= init_size
;
475 while (remaining
> 0)
479 SCM_SYSCALL (count
= write (fp
->fdes
, ptr
, remaining
));
482 /* error. assume nothing was written this call, but
483 fix up the buffer for any previous successful writes. */
484 int done
= init_size
- remaining
;
490 for (i
= 0; i
< remaining
; i
++)
492 *(pt
->write_buf
+ i
) = *(pt
->write_buf
+ done
+ i
);
494 pt
->write_pos
= pt
->write_buf
+ remaining
;
497 scm_syserror ("local_fflush");
500 const char *msg
= "Error: could not flush file-descriptor ";
503 write (2, msg
, strlen (msg
));
504 sprintf (buf
, "%d\n", fp
->fdes
);
505 write (2, buf
, strlen (buf
));
513 pt
->write_pos
= pt
->write_buf
;
517 /* clear the read buffer and adjust the file position for unread bytes. */
519 local_read_flush (SCM port
, int offset
)
521 struct scm_fport
*fp
= SCM_FSTREAM (port
);
522 scm_port
*pt
= SCM_PTAB_ENTRY (port
);
524 offset
+= pt
->read_end
- pt
->read_pos
;
528 pt
->read_pos
= pt
->read_end
;
529 /* will throw error if unread-char used at beginning of file
530 then attempting to write. seems correct. */
531 if (lseek (fp
->fdes
, -offset
, SEEK_CUR
) == -1)
532 scm_syserror ("local_read_flush");
538 local_fclose (SCM port
)
540 struct scm_fport
*fp
= SCM_FSTREAM (port
);
541 scm_port
*pt
= SCM_PTAB_ENTRY (port
);
545 SCM_SYSCALL (rv
= close (fp
->fdes
));
546 if (rv
== -1 && errno
!= EBADF
)
547 scm_syserror ("local_fclose");
548 if (pt
->read_buf
== pt
->putback_buf
)
549 pt
->read_buf
= pt
->saved_read_buf
;
550 if (pt
->read_buf
!= &pt
->shortbuf
)
552 if (pt
->write_buf
!= &pt
->shortbuf
)
553 free (pt
->write_buf
);
559 local_free (SCM port
)
565 void scm_make_fptob (void); /* Called from ports.c */
570 long tc
= scm_make_port_type ("file", fport_fill_buffer
, local_fflush
);
571 scm_set_port_free (tc
, local_free
);
572 scm_set_port_print (tc
, prinfport
);
573 scm_set_port_flush_input (tc
, local_read_flush
);
574 scm_set_port_close (tc
, local_fclose
);
575 scm_set_port_seek (tc
, local_seek
);
576 scm_set_port_truncate (tc
, local_ftruncate
);
577 scm_set_port_input_waiting_p (tc
, fport_input_waiting_p
);
584 scm_sysintern ("_IOFBF", SCM_MAKINUM (_IOFBF
));
585 scm_sysintern ("_IOLBF", SCM_MAKINUM (_IOLBF
));
586 scm_sysintern ("_IONBF", SCM_MAKINUM (_IONBF
));