1 /* Copyright (C) 1995,1996,1997 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. */
59 /* Port direction --- handling el cheapo stdio implementations.
61 Guile says that when you've got a port that's both readable and
62 writable, like a socket, why then, by gum, you can read from it and
63 write to it! However, most standard I/O implementations make
64 cheezy caveats like this:
66 When a file is opened for update, both input and output may
67 be done on the resulting stream. However, output may not be
68 directly followed by input without an intervening fflush(),
69 fseek(), fsetpos(), or rewind(), and input may not be
70 directly followed by output without an intervening fseek(),
71 fsetpos(), or rewind(), or an input operation that
72 encounters end-of-file.
73 -- the Solaris fdopen(3S) man page
75 I think this behavior is permitted by the ANSI C standard.
77 So we made the implementation more complex, so what the user sees
78 remains simple. When we have a Guile port based on a stdio stream
79 (this source file's specialty), we keep track of whether it was
80 last written to, read from, or whether it is in a safe state for
81 both operations. Each port operation function just checks the
82 state of the port before each operation, and does the required
85 We use two bits in the CAR of the port, FPORT_READ_SAFE and
86 FPORT_WRITE_SAFE, to indicate what operations the underlying stdio
87 stream could correctly perform next. You're not allowed to clear
88 them both at the same time, but both can be set --- for example, if
89 the stream has just been opened, or flushed, or had its position
92 It's possible for a port to have neither bit set, if we receive a
93 FILE * pointer in an unknown state; this code should handle that
96 #define FPORT_READ_SAFE (1L << 24)
97 #define FPORT_WRITE_SAFE (2L << 24)
99 #define FPORT_ALL_OKAY(port) \
100 (SCM_SETOR_CAR (port, (FPORT_READ_SAFE | FPORT_WRITE_SAFE)))
105 if (! (SCM_CAR (port
) & FPORT_READ_SAFE
))
106 fflush ((FILE *)SCM_STREAM (port
));
108 /* We've done the flush, so reading is safe.
109 Assuming that we're going to do a read next, writing will not be
110 safe by the time we're done. */
111 SCM_SETOR_CAR (port
, FPORT_READ_SAFE
);
112 SCM_SETAND_CAR (port
, ~FPORT_WRITE_SAFE
);
119 if (! (SCM_CAR (port
) & FPORT_WRITE_SAFE
))
120 /* This can fail, if we're talking to a line-buffered terminal. As
121 far as I can tell, there's no way to get mixed reads and writes
122 to work on a line-buffered terminal at all --- you get a full
123 line in the buffer when you read, and then you have to throw it
124 out to write. You have to do unbuffered input, and make the
125 system provide the second buffer. */
126 fseek ((FILE *)SCM_STREAM (port
), 0, SEEK_CUR
);
128 /* We've done the seek, so writing is safe.
129 Assuming that we're going to do a write next, reading will not be
130 safe by the time we're done. */
131 SCM_SETOR_CAR (port
, FPORT_WRITE_SAFE
);
132 SCM_SETAND_CAR (port
, ~FPORT_READ_SAFE
);
136 /* Helpful operations on stdio FILE-based ports */
138 /* should be called with SCM_DEFER_INTS active */
144 /* NOSETBUF was provided by scm to allow unbuffered ports to be
145 avoided on systems where ungetc didn't work correctly. See
146 comment in unif.c, which seems to be the only place where it
147 could still be a problem. */
149 /* SCM_SYSCALL (setbuf ((FILE *)SCM_STREAM (port), 0);); */
150 SCM_SYSCALL (setvbuf ((FILE *)SCM_STREAM (port
), 0, _IONBF
, 0););
152 return SCM_UNSPECIFIED
;
155 SCM_PROC (s_setvbuf
, "setvbuf", 2, 1, 0, scm_setvbuf
);
157 scm_setvbuf (SCM port
, SCM mode
, SCM size
)
162 port
= SCM_COERCE_OUTPORT (port
);
164 SCM_ASSERT (SCM_NIMP (port
) && SCM_FPORTP (port
), port
, SCM_ARG1
, s_setvbuf
);
165 SCM_ASSERT (SCM_INUMP (mode
), mode
, SCM_ARG2
, s_setvbuf
);
166 if (SCM_UNBNDP (size
))
170 SCM_ASSERT (SCM_INUMP (size
), size
, SCM_ARG3
, s_setvbuf
);
171 csize
= SCM_INUM (size
);
173 cmode
= SCM_INUM (mode
);
174 if (csize
== 0 && cmode
== _IOFBF
)
177 SCM_SYSCALL (rv
= setvbuf ((FILE *)SCM_STREAM (port
), 0, cmode
, csize
));
179 scm_syserror (s_setvbuf
);
181 SCM_SETCAR (port
, SCM_CAR (port
) | SCM_BUF0
);
183 SCM_SETCAR (port
, (SCM_CAR (port
) & ~SCM_BUF0
));
185 return SCM_UNSPECIFIED
;
189 #define SET_FILE_FD_FIELD(F,D) ((F)->FD_SETTER = (D))
193 scm_setfileno (fs
, fd
)
197 #ifdef SET_FILE_FD_FIELD
198 SET_FILE_FD_FIELD(fs
, fd
);
200 scm_misc_error ("scm_setfileno", "Not fully implemented on this platform",
205 /* Move ports with the specified file descriptor to new descriptors,
206 * reseting the revealed count to 0.
207 * Should be called with SCM_DEFER_INTS active.
216 for (i
= 0; i
< scm_port_table_size
; i
++)
218 if (SCM_FPORTP (scm_port_table
[i
]->port
)
219 && fileno ((FILE *)SCM_STREAM (scm_port_table
[i
]->port
)) == fd
)
221 scm_setfileno ((FILE *)SCM_STREAM (scm_port_table
[i
]->port
), dup (fd
));
222 scm_set_port_revealed_x (scm_port_table
[i
]->port
, SCM_MAKINUM (0));
228 * Return a new port open on a given file.
230 * The mode string must match the pattern: [rwa+]** which
231 * is interpreted in the usual unix way.
233 * Return the new port.
235 SCM_PROC(s_open_file
, "open-file", 2, 0, 0, scm_open_file
);
238 scm_open_file (filename
, modes
)
247 SCM_ASSERT (SCM_NIMP (filename
) && SCM_ROSTRINGP (filename
), filename
, SCM_ARG1
, s_open_file
);
248 SCM_ASSERT (SCM_NIMP (modes
) && SCM_ROSTRINGP (modes
), modes
, SCM_ARG2
, s_open_file
);
249 if (SCM_SUBSTRP (filename
))
250 filename
= scm_makfromstr (SCM_ROCHARS (filename
), SCM_ROLENGTH (filename
), 0);
251 if (SCM_SUBSTRP (modes
))
252 modes
= scm_makfromstr (SCM_ROCHARS (modes
), SCM_ROLENGTH (modes
), 0);
254 file
= SCM_ROCHARS (filename
);
255 mode
= SCM_ROCHARS (modes
);
258 SCM_SYSCALL (f
= fopen (file
, mode
));
263 scm_syserror_msg (s_open_file
, "%s: %S",
264 scm_listify (scm_makfrom0str (strerror (errno
)),
270 port
= scm_stdio_to_port (f
, mode
, filename
);
276 SCM_PROC (s_freopen
, "freopen", 3, 0, 0, scm_freopen
);
279 scm_freopen (filename
, modes
, port
)
285 SCM_ASSERT (SCM_NIMP (filename
) && SCM_ROSTRINGP (filename
), filename
,
286 SCM_ARG1
, s_freopen
);
287 SCM_ASSERT (SCM_NIMP (modes
) && SCM_ROSTRINGP (modes
), modes
, SCM_ARG2
,
290 SCM_COERCE_SUBSTR (filename
);
291 SCM_COERCE_SUBSTR (modes
);
292 port
= SCM_COERCE_OUTPORT (port
);
294 SCM_ASSERT (SCM_NIMP (port
) && SCM_FPORTP (port
), port
, SCM_ARG3
, s_freopen
);
295 SCM_SYSCALL (f
= freopen (SCM_ROCHARS (filename
), SCM_ROCHARS (modes
),
296 (FILE *)SCM_STREAM (port
)));
301 port
= SCM_MAKINUM (errno
);
302 SCM_SETAND_CAR (p
, ~SCM_OPN
);
303 scm_remove_from_port_table (p
);
307 SCM_SETSTREAM (port
, (SCM
)f
);
308 SCM_SETCAR (port
, (scm_tc16_fport
309 | scm_mode_bits (SCM_ROCHARS (modes
))
310 | FPORT_READ_SAFE
| FPORT_WRITE_SAFE
));
311 if (SCM_BUF0
& SCM_CAR (port
))
320 /* Building Guile ports from stdio FILE pointers. */
322 /* Build a Scheme port from an open stdio port, FILE.
323 MODE indicates whether FILE is open for reading or writing; it uses
324 the same notation as open-file's second argument.
325 Use NAME as the port's filename. */
327 scm_stdio_to_port (FILE *file
, char *mode
, SCM name
)
329 long mode_bits
= scm_mode_bits (mode
);
331 struct scm_port_table
* pt
;
336 pt
= scm_add_to_port_table (port
);
337 SCM_SETPTAB_ENTRY (port
, pt
);
338 SCM_SETCAR (port
, (scm_tc16_fport
340 | FPORT_READ_SAFE
| FPORT_WRITE_SAFE
));
341 SCM_SETSTREAM (port
, (SCM
) file
);
342 if (SCM_BUF0
& SCM_CAR (port
))
344 SCM_PTAB_ENTRY (port
)->file_name
= name
;
351 /* Like scm_stdio_to_port, except that:
352 - NAME is a standard C string, not a Guile string
353 - we set the revealed count for FILE's file descriptor to 1, so
354 that FILE won't be closed when the port object is GC'd. */
356 scm_standard_stream_to_port (FILE *file
, char *mode
, char *name
)
358 SCM port
= scm_stdio_to_port (file
, mode
, scm_makfrom0str (name
));
359 scm_set_port_revealed_x (port
, SCM_MAKINUM (1));
365 /* The fport and pipe port scm_ptobfuns functions --- reading and writing */
367 static int prinfport
SCM_P ((SCM exp
, SCM port
, scm_print_state
*pstate
));
370 prinfport (exp
, port
, pstate
)
373 scm_print_state
*pstate
;
377 if (SCM_CLOSEDP (exp
))
383 name
= SCM_PTAB_ENTRY (exp
)->file_name
;
384 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
385 c
= SCM_ROCHARS (name
);
390 scm_prinport (exp
, port
, c
);
397 local_fgetc (SCM port
)
399 FILE *s
= (FILE *) SCM_STREAM (port
);
409 local_fgets (SCM port
, int *len
)
414 char *p
; /* pointer to current buffer position */
415 int limit
= 80; /* current size of buffer */
419 /* If this is a socket port or something where we can't rely on
420 ftell to determine how much we've read, then call the generic
421 function. We could use a separate scm_ptobfuns table with
422 scm_generic_fgets, but then we'd have to change SCM_FPORTP, etc.
423 Ideally, it should become something that means "this port has a
424 file descriptor"; sometimes we reject sockets when we shouldn't.
425 But I'm too stupid at the moment to do that right. */
426 if (SCM_CAR (port
) & SCM_NOFTELL
)
427 return scm_generic_fgets (port
, len
);
429 f
= (FILE *) SCM_STREAM (port
);
433 buf
= (char *) malloc (limit
* sizeof(char));
436 /* If a char has been pushed onto the port with scm_ungetc,
438 if (SCM_CRDYP (port
))
440 buf
[*len
] = SCM_CGETUN (port
);
442 if (buf
[(*len
)++] == '\n')
451 int chunk_size
= limit
- *len
;
452 long int numread
, pos
;
456 /* We must use ftell to figure out how many characters were read.
457 If there are null characters near the end of file, and no
458 terminating newline, there is no other way to tell the difference
459 between an embedded null and the string-terminating null. */
462 if (fgets (p
, chunk_size
, f
) == NULL
) {
468 numread
= ftell (f
) - pos
;
471 if (numread
< chunk_size
- 1 || buf
[limit
-2] == '\n')
474 buf
= (char *) realloc (buf
, sizeof(char) * limit
* 2);
481 static scm_sizet pwrite
SCM_P ((char *ptr
, scm_sizet size
, nitems
, FILE *port
));
484 pwrite (ptr
, size
, nitems
, port
)
486 scm_sizet size
, nitems
;
489 scm_sizet len
= size
* nitems
;
496 #define ffwrite pwrite
498 #define ffwrite fwrite
502 local_fclose (SCM port
)
504 FILE *fp
= (FILE *) SCM_STREAM (port
);
510 local_fflush (SCM port
)
512 FILE *fp
= (FILE *) SCM_STREAM (port
);
514 FPORT_ALL_OKAY (port
);
518 local_fputc (int c
, SCM port
)
520 FILE *fp
= (FILE *) SCM_STREAM (port
);
523 return fputc (c
, fp
);
527 local_fputs (char *s
, SCM port
)
529 FILE *fp
= (FILE *) SCM_STREAM (port
);
531 return fputs (s
, fp
);
535 local_ffwrite (char *ptr
,
540 FILE *fp
= (FILE *) SCM_STREAM (port
);
542 return ffwrite (ptr
, size
, nitems
, fp
);
546 print_pipe_port (SCM exp
, SCM port
, scm_print_state
*pstate
)
548 scm_prinport (exp
, port
, "pipe");
553 local_pclose (SCM port
)
555 FILE *fp
= (FILE *) SCM_STREAM (port
);
561 /* The file and pipe port scm_ptobfuns structures themselves. */
563 scm_ptobfuns scm_fptob
=
579 scm_ptobfuns scm_pipob
=
598 scm_sysintern ("_IOFBF", SCM_MAKINUM (_IOFBF
));
599 scm_sysintern ("_IOLBF", SCM_MAKINUM (_IOLBF
));
600 scm_sysintern ("_IONBF", SCM_MAKINUM (_IONBF
));