1 /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 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. */
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
49 #include "libguile/_scm.h"
50 #include "libguile/ioext.h"
51 #include "libguile/fports.h"
52 #include "libguile/feature.h"
53 #include "libguile/ports.h"
54 #include "libguile/root.h"
55 #include "libguile/strings.h"
56 #include "libguile/validate.h"
69 #define SCM_MAYBE_EAGAIN || errno == EAGAIN
71 #define SCM_MAYBE_EAGAIN
74 #if defined (EWOULDBLOCK)
75 #define SCM_MAYBE_EWOULDBLOCK || errno == EWOULDBLOCK
77 #define SCM_MAYBE_EWOULDBLOCK
80 /* MAYBE there is EAGAIN way of defining this macro but now I EWOULDBLOCK. */
81 #define SCM_EBLOCK(errno) \
82 (0 SCM_MAYBE_EAGAIN SCM_MAYBE_EWOULDBLOCK)
84 SCM_DEFINE (scm_read_string_x_partial
, "read-string!/partial", 1, 3, 0,
85 (SCM str
, SCM port_or_fdes
, SCM start
, SCM end
),
86 "Read characters from an fport or file descriptor into a\n"
87 "string @var{str}. This procedure is scsh-compatible\n"
88 "and can efficiently read large strings. It will:\n\n"
91 "attempt to fill the entire string, unless the @var{start}\n"
92 "and/or @var{end} arguments are supplied. i.e., @var{start}\n"
93 "defaults to 0 and @var{end} defaults to\n"
94 "@code{(string-length str)}\n"
96 "use the current input port if @var{port_or_fdes} is not\n"
99 "read any characters that are currently available,\n"
100 "without waiting for the rest (short reads are possible).\n\n"
102 "wait for as long as it needs to for the first character to\n"
103 "become available, unless the port is in non-blocking mode\n"
105 "return @code{#f} if end-of-file is encountered before reading\n"
106 "any characters, otherwise return the number of characters\n"
109 "return 0 if the port is in non-blocking mode and no characters\n"
110 "are immediately available.\n"
112 "return 0 if the request is for 0 bytes, with no\n"
113 "end-of-file check\n"
115 #define FUNC_NAME s_scm_read_string_x_partial
126 SCM_VALIDATE_SUBSTRING_SPEC_COPY (1, str
, dest
, 3, start
, offset
,
129 read_len
= last
- offset
;
132 if (SCM_INUMP (port_or_fdes
))
133 fdes
= SCM_INUM (port_or_fdes
);
136 SCM port
= SCM_UNBNDP (port_or_fdes
) ? scm_cur_inp
: port_or_fdes
;
138 SCM_VALIDATE_OPFPORT (2, port
);
139 SCM_VALIDATE_INPUT_PORT (2, port
);
141 /* if there's anything in the port buffers, use it, but then
142 don't touch the file descriptor. otherwise the
143 "return immediately if something is available" rule may
145 chars_read
= scm_take_from_input_buffers (port
, dest
, read_len
);
146 fdes
= SCM_FPORT_FDES (port
);
149 if (chars_read
== 0 && read_len
> 0) /* don't confuse read_len == 0 with
152 SCM_SYSCALL (chars_read
= read (fdes
, dest
, read_len
));
153 if (chars_read
== -1)
155 if (SCM_EBLOCK (errno
))
160 else if (chars_read
== 0)
163 return scm_long2num (chars_read
);
167 SCM_DEFINE (scm_ftell
, "ftell", 1, 0, 0,
169 "Returns an integer representing the current position of @var{fd/port},\n"
170 "measured from the beginning. Equivalent to:\n"
172 "(seek port 0 SEEK_CUR)\n"
174 #define FUNC_NAME s_scm_ftell
176 return scm_seek (object
, SCM_INUM0
, SCM_MAKINUM (SEEK_CUR
));
181 #if (SCM_DEBUG_DEPRECATED == 0)
183 SCM_DEFINE (scm_fseek
, "fseek", 3, 0, 0,
184 (SCM object
, SCM offset
, SCM whence
),
185 "Obsolete. Almost the same as seek, above, but the return value is\n"
187 #define FUNC_NAME s_scm_fseek
189 scm_seek (object
, offset
, whence
);
190 return SCM_UNSPECIFIED
;
194 #endif /* SCM_DEBUG_DEPRECATED == 0 */
197 SCM_DEFINE (scm_redirect_port
, "redirect-port", 2, 0, 0,
199 "This procedure takes two ports and duplicates the underlying file\n"
200 "descriptor from @var{old-port} into @var{new-port}. The\n"
201 "current file descriptor in @var{new-port} will be closed.\n"
202 "After the redirection the two ports will share a file position\n"
203 "and file status flags.\n\n"
204 "The return value is unspecified.\n\n"
205 "Unexpected behaviour can result if both ports are subsequently used\n"
206 "and the original and/or duplicate ports are buffered.\n\n"
207 "This procedure does not have any side effects on other ports or\n"
209 #define FUNC_NAME s_scm_redirect_port
211 int ans
, oldfd
, newfd
;
212 struct scm_fport
*fp
;
214 old
= SCM_COERCE_OUTPORT (old
);
215 new = SCM_COERCE_OUTPORT (new);
217 SCM_VALIDATE_OPFPORT (1,old
);
218 SCM_VALIDATE_OPFPORT (2,new);
219 oldfd
= SCM_FPORT_FDES (old
);
220 fp
= SCM_FSTREAM (new);
224 scm_port
*pt
= SCM_PTAB_ENTRY (new);
225 scm_port
*old_pt
= SCM_PTAB_ENTRY (old
);
226 scm_ptob_descriptor
*ptob
= &scm_ptobs
[SCM_PTOBNUM (new)];
228 /* must flush to old fdes. */
229 if (pt
->rw_active
== SCM_PORT_WRITE
)
231 else if (pt
->rw_active
== SCM_PORT_READ
)
233 ans
= dup2 (oldfd
, newfd
);
236 pt
->rw_random
= old_pt
->rw_random
;
237 /* continue using existing buffers, even if inappropriate. */
239 return SCM_UNSPECIFIED
;
243 SCM_DEFINE (scm_dup_to_fdes
, "dup->fdes", 1, 1, 0,
244 (SCM fd_or_port
, SCM fd
),
245 "Returns an integer file descriptor.")
246 #define FUNC_NAME s_scm_dup_to_fdes
248 int oldfd
, newfd
, rv
;
250 fd_or_port
= SCM_COERCE_OUTPORT (fd_or_port
);
252 if (SCM_INUMP (fd_or_port
))
253 oldfd
= SCM_INUM (fd_or_port
);
256 SCM_VALIDATE_OPFPORT (1,fd_or_port
);
257 oldfd
= SCM_FPORT_FDES (fd_or_port
);
265 fd
= SCM_MAKINUM (newfd
);
269 SCM_VALIDATE_INUM_COPY (2, fd
, newfd
);
272 scm_evict_ports (newfd
); /* see scsh manual. */
273 rv
= dup2 (oldfd
, newfd
);
283 SCM_DEFINE (scm_dup2
, "dup2", 2, 0, 0,
284 (SCM oldfd
, SCM newfd
),
285 "A simple wrapper for the @code{dup2} system call.\n"
286 "Copies the file descriptor @var{oldfd} to descriptor\n"
287 "number @var{newfd}, replacing the previous meaning\n"
288 "of @var{newfd}. Both @var{oldfd} and @var{newfd} must\n"
290 "Unlike for dup->fdes or primitive-move->fdes, no attempt\n"
291 "is made to move away ports which are using @var{newfd}.\n"
292 "The return value is unspecified.")
293 #define FUNC_NAME s_scm_dup2
299 SCM_VALIDATE_INUM_COPY (1, oldfd
, c_oldfd
);
300 SCM_VALIDATE_INUM_COPY (2, newfd
, c_newfd
);
301 rv
= dup2 (c_oldfd
, c_newfd
);
304 return SCM_UNSPECIFIED
;
308 SCM_DEFINE (scm_fileno
, "fileno", 1, 0, 0,
310 "Returns the integer file descriptor underlying @var{port}.\n"
311 "Does not change its revealed count.")
312 #define FUNC_NAME s_scm_fileno
314 port
= SCM_COERCE_OUTPORT (port
);
315 SCM_VALIDATE_OPFPORT (1,port
);
316 return SCM_MAKINUM (SCM_FPORT_FDES (port
));
320 /* GJB:FIXME:: why does this not throw
321 an error if the arg is not a port?
322 This proc as is would be better names isattyport?
323 if it is not going to assume that the arg is a port */
324 SCM_DEFINE (scm_isatty_p
, "isatty?", 1, 0, 0,
326 "Returns @code{#t} if @var{port} is using a serial\n"
327 "non-file device, otherwise @code{#f}.")
328 #define FUNC_NAME s_scm_isatty_p
332 port
= SCM_COERCE_OUTPORT (port
);
334 if (!SCM_OPFPORTP (port
))
337 rv
= isatty (SCM_FPORT_FDES (port
));
344 SCM_DEFINE (scm_fdopen
, "fdopen", 2, 0, 0,
345 (SCM fdes
, SCM modes
),
346 "Returns a new port based on the file descriptor @var{fdes}.\n"
347 "Modes are given by the string @var{modes}. The revealed count of the port\n"
348 "is initialized to zero. The modes string is the same as that accepted\n"
349 "by @ref{File Ports, open-file}.")
350 #define FUNC_NAME s_scm_fdopen
352 SCM_VALIDATE_INUM (1,fdes
);
353 SCM_VALIDATE_STRING (2, modes
);
354 SCM_STRING_COERCE_0TERMINATION_X (modes
);
356 return scm_fdes_to_port (SCM_INUM (fdes
), SCM_STRING_CHARS (modes
), SCM_BOOL_F
);
362 /* Move a port's underlying file descriptor to a given value.
363 * Returns #f if fdes is already the given value.
365 * MOVE->FDES is implemented in Scheme and calls this primitive.
367 SCM_DEFINE (scm_primitive_move_to_fdes
, "primitive-move->fdes", 2, 0, 0,
369 "Moves the underlying file descriptor for @var{port} to the integer\n"
370 "value @var{fdes} without changing the revealed count of @var{port}.\n"
371 "Any other ports already using this descriptor will be automatically\n"
372 "shifted to new descriptors and their revealed counts reset to zero.\n"
373 "The return value is @code{#f} if the file descriptor already had the\n"
374 "required value or @code{#t} if it was moved.")
375 #define FUNC_NAME s_scm_primitive_move_to_fdes
377 struct scm_fport
*stream
;
382 port
= SCM_COERCE_OUTPORT (port
);
384 SCM_VALIDATE_OPFPORT (1,port
);
385 SCM_VALIDATE_INUM (2,fd
);
386 stream
= SCM_FSTREAM (port
);
387 old_fd
= stream
->fdes
;
388 new_fd
= SCM_INUM (fd
);
389 if (old_fd
== new_fd
)
393 scm_evict_ports (new_fd
);
394 rv
= dup2 (old_fd
, new_fd
);
397 stream
->fdes
= new_fd
;
398 SCM_SYSCALL (close (old_fd
));
403 /* Return a list of ports using a given file descriptor. */
404 SCM_DEFINE (scm_fdes_to_ports
, "fdes->ports", 1, 0, 0,
406 "Returns a list of existing ports which have @var{fdes} as an\n"
407 "underlying file descriptor, without changing their revealed counts.")
408 #define FUNC_NAME s_scm_fdes_to_ports
410 SCM result
= SCM_EOL
;
414 SCM_VALIDATE_INUM_COPY (1,fd
,int_fd
);
416 for (i
= 0; i
< scm_port_table_size
; i
++)
418 if (SCM_OPFPORTP (scm_port_table
[i
]->port
)
419 && ((struct scm_fport
*) scm_port_table
[i
]->stream
)->fdes
== int_fd
)
420 result
= scm_cons (scm_port_table
[i
]->port
, result
);
430 scm_add_feature ("i/o-extensions");
432 #ifndef SCM_MAGIC_SNARFER
433 #include "libguile/ioext.x"