* configure.in: Added thread support for the alpha architecture.
[bpt/guile.git] / libguile / ioext.c
CommitLineData
1146b6cd 1/* Copyright (C) 1995, 1996, 1997 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
44#include <stdio.h>
0f2d19dd 45#include "_scm.h"
1146b6cd
GH
46#include "genio.h"
47#include "read.h"
20e6290e 48#include "fports.h"
1146b6cd
GH
49#include "unif.h"
50#include "chars.h"
20e6290e
JB
51
52#include "ioext.h"
0f2d19dd 53
95b88819
GH
54#ifdef HAVE_STRING_H
55#include <string.h>
56#endif
57#ifdef HAVE_UNISTD_H
58#include <unistd.h>
59#endif
0f2d19dd
JB
60\f
61
1146b6cd
GH
62SCM_PROC (s_read_delimited_x, "%read-delimited!", 3, 3, 0, scm_read_delimited_x);
63
64SCM
65scm_read_delimited_x (delims, buf, gobble, port, start, end)
66 SCM delims;
67 SCM buf;
68 SCM gobble;
69 SCM port;
70 SCM start;
71 SCM end;
72{
73 long j;
74 char *cbuf;
75 long cstart;
76 long cend;
77 int c;
78 char *cdelims;
79 int num_delims;
80
ae2fa5bc 81 SCM_ASSERT (SCM_NIMP (delims) && SCM_ROSTRINGP (delims),
1146b6cd 82 delims, SCM_ARG1, s_read_delimited_x);
ae2fa5bc
GH
83 cdelims = SCM_ROCHARS (delims);
84 num_delims = SCM_ROLENGTH (delims);
1146b6cd
GH
85 SCM_ASSERT (SCM_NIMP (buf) && SCM_STRINGP (buf),
86 buf, SCM_ARG2, s_read_delimited_x);
87 cbuf = SCM_CHARS (buf);
88 cend = SCM_LENGTH (buf);
89 if (SCM_UNBNDP (port))
90 port = scm_cur_inp;
91 else
92 {
93 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port),
94 port, SCM_ARG1, s_read_delimited_x);
95 }
96
97 if (SCM_UNBNDP (start))
98 cstart = 0;
99 else
100 {
101 cstart = scm_num2long (start,
102 (char *) SCM_ARG5, s_read_delimited_x);
103 if (cstart < 0 || cstart >= cend)
104 scm_out_of_range (s_read_delimited_x, start);
105
106 if (!SCM_UNBNDP (end))
107 {
108 long tend = scm_num2long (end, (char *) SCM_ARG6,
109 s_read_delimited_x);
110 if (tend <= cstart || tend > cend)
111 scm_out_of_range (s_read_delimited_x, end);
112 cend = tend;
113 }
114 }
115
116 for (j = cstart; j < cend; j++)
117 {
118 int k;
119
120 c = scm_gen_getc (port);
121 for (k = 0; k < num_delims; k++)
122 {
123 if (cdelims[k] == c)
124 {
125 if (SCM_FALSEP (gobble))
126 scm_gen_ungetc (c, port);
127
128 return scm_cons (SCM_MAKICHR (c),
129 scm_long2num (j - cstart));
130 }
131 }
132 if (c == EOF)
133 return scm_cons (SCM_EOF_VAL,
134 scm_long2num (j - cstart));
135
136 cbuf[j] = c;
137 }
138 return scm_cons (SCM_BOOL_F, scm_long2num (j - cstart));
139}
140
141SCM_PROC (s_write_line, "write-line", 1, 1, 0, scm_write_line);
142
143SCM
144scm_write_line (obj, port)
145 SCM obj;
146 SCM port;
147{
148 scm_display (obj, port);
149 return scm_newline (port);
150}
151
063e05be 152SCM_PROC (s_ftell, "ftell", 1, 0, 0, scm_ftell);
1cc91f1b 153
0f2d19dd 154SCM
063e05be 155scm_ftell (port)
0f2d19dd 156 SCM port;
0f2d19dd
JB
157{
158 long pos;
063e05be 159 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_ftell);
0f2d19dd
JB
160 SCM_SYSCALL (pos = ftell ((FILE *)SCM_STREAM (port)));
161 if (pos < 0)
063e05be 162 scm_syserror (s_ftell);
0f2d19dd
JB
163 if (pos > 0 && SCM_CRDYP (port))
164 pos--;
8588fa12 165 return scm_long2num (pos);
0f2d19dd
JB
166}
167
168
169
063e05be 170SCM_PROC (s_fseek, "fseek", 3, 0, 0, scm_fseek);
1cc91f1b 171
0f2d19dd 172SCM
063e05be 173scm_fseek (port, offset, whence)
0f2d19dd
JB
174 SCM port;
175 SCM offset;
176 SCM whence;
0f2d19dd
JB
177{
178 int rv;
8588fa12
GH
179 long loff;
180
063e05be
GH
181 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_fseek);
182 loff = scm_num2long (offset, (char *)SCM_ARG2, s_fseek);
0f2d19dd 183 SCM_ASSERT (SCM_INUMP (whence) && (SCM_INUM (whence) < 3) && (SCM_INUM (whence) >= 0),
063e05be 184 whence, SCM_ARG3, s_fseek);
8588fa12 185
0f2d19dd
JB
186 SCM_CLRDY (port); /* Clear ungetted char */
187 /* Values of whence are interned in scm_init_ioext. */
8588fa12 188 rv = fseek ((FILE *)SCM_STREAM (port), loff, SCM_INUM (whence));
02b754d3 189 if (rv != 0)
063e05be 190 scm_syserror (s_fseek);
02b754d3 191 return SCM_UNSPECIFIED;
0f2d19dd
JB
192}
193
194
195
063e05be 196SCM_PROC (s_freopen, "freopen", 3, 0, 0, scm_freopen);
1cc91f1b 197
0f2d19dd 198SCM
063e05be 199scm_freopen (filename, modes, port)
0f2d19dd
JB
200 SCM filename;
201 SCM modes;
202 SCM port;
0f2d19dd
JB
203{
204 FILE *f;
ae2fa5bc
GH
205 SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename,
206 SCM_ARG1, s_freopen);
207 SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2,
208 s_freopen);
89958ad0
JB
209
210 SCM_COERCE_SUBSTR (filename);
211 SCM_COERCE_SUBSTR (modes);
0f2d19dd 212 SCM_DEFER_INTS;
063e05be 213 SCM_ASSERT (SCM_NIMP (port) && SCM_FPORTP (port), port, SCM_ARG3, s_freopen);
ae2fa5bc
GH
214 SCM_SYSCALL (f = freopen (SCM_ROCHARS (filename), SCM_ROCHARS (modes),
215 (FILE *)SCM_STREAM (port)));
0f2d19dd
JB
216 if (!f)
217 {
218 SCM p;
219 p = port;
220 port = SCM_MAKINUM (errno);
898a256f 221 SCM_SETAND_CAR (p, ~SCM_OPN);
0f2d19dd
JB
222 scm_remove_from_port_table (p);
223 }
224 else
225 {
ae2fa5bc 226 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
0f2d19dd 227 SCM_SETSTREAM (port, (SCM)f);
ae2fa5bc 228 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
898a256f 229 if (SCM_BUF0 & SCM_CAR (port))
0f2d19dd
JB
230 scm_setbuf0 (port);
231 }
232 SCM_ALLOW_INTS;
233 return port;
234}
235
063e05be 236SCM_PROC (s_redirect_port, "redirect-port", 2, 0, 0, scm_redirect_port);
1cc91f1b 237
0f2d19dd 238SCM
9c29ac66
GH
239scm_redirect_port (old, new)
240 SCM old;
241 SCM new;
0f2d19dd
JB
242{
243 int ans, oldfd, newfd;
9c29ac66 244
0f2d19dd 245 SCM_DEFER_INTS;
9c29ac66
GH
246 SCM_ASSERT (SCM_NIMP (old) && SCM_OPPORTP (old), old, SCM_ARG1, s_redirect_port);
247 SCM_ASSERT (SCM_NIMP (new) && SCM_OPPORTP (new), new, SCM_ARG2, s_redirect_port);
248 oldfd = fileno ((FILE *)SCM_STREAM (old));
02b754d3 249 if (oldfd == -1)
063e05be 250 scm_syserror (s_redirect_port);
9c29ac66 251 newfd = fileno ((FILE *)SCM_STREAM (new));
02b754d3 252 if (newfd == -1)
063e05be 253 scm_syserror (s_redirect_port);
02b754d3
GH
254 SCM_SYSCALL (ans = dup2 (oldfd, newfd));
255 if (ans == -1)
063e05be 256 scm_syserror (s_redirect_port);
0f2d19dd 257 SCM_ALLOW_INTS;
02b754d3 258 return SCM_UNSPECIFIED;
0f2d19dd
JB
259}
260
a9488d12
GH
261SCM_PROC (s_primitive_dup, "primitive-dup", 1, 0, 0, scm_primitive_dup);
262SCM
263scm_primitive_dup (SCM fd_or_port)
264{
265 int fd, newfd;
266
267 SCM_DEFER_INTS;
268 if (SCM_INUMP (fd_or_port))
269 fd = SCM_INUM (fd_or_port);
270 else
271 {
272 SCM_ASSERT (SCM_NIMP (fd_or_port) && SCM_OPPORTP (fd_or_port),
273 fd_or_port, SCM_ARG1, s_primitive_dup);
274 fd = fileno ((FILE *)SCM_STREAM (fd_or_port));
275 if (fd == -1)
276 scm_syserror (s_primitive_dup);
277 }
278 SCM_SYSCALL (newfd = dup (fd));
279 if (newfd == -1)
280 scm_syserror (s_primitive_dup);
281 SCM_ALLOW_INTS;
282 return SCM_MAKINUM (newfd);
283}
284
285SCM_PROC (s_primitive_dup2, "primitive-dup2", 2, 0, 0, scm_primitive_dup2);
286SCM
287scm_primitive_dup2 (SCM fd_or_port, SCM fd)
288{
289 int oldfd, newfd, rv;
290
291 SCM_DEFER_INTS;
292 if (SCM_INUMP (fd_or_port))
293 oldfd = SCM_INUM (fd_or_port);
294 else
295 {
296 SCM_ASSERT (SCM_NIMP (fd_or_port) && SCM_OPPORTP (fd_or_port),
297 fd_or_port, SCM_ARG1, s_primitive_dup2);
298 oldfd = fileno ((FILE *)SCM_STREAM (fd_or_port));
299 if (oldfd == -1)
300 scm_syserror (s_primitive_dup2);
301 }
302
e38303a2 303 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG2, s_primitive_dup2);
a9488d12 304 newfd = SCM_INUM (fd);
e38303a2
GH
305 if (oldfd == newfd)
306 {
307 SCM_ALLOW_INTS;
308 return fd;
309 }
a9488d12
GH
310 scm_evict_ports (newfd); /* see scsh manual. */
311 SCM_SYSCALL (rv = dup2 (oldfd, newfd));
312 if (rv == -1)
313 scm_syserror (s_primitive_dup2);
314 SCM_ALLOW_INTS;
e38303a2 315 return fd;
a9488d12
GH
316}
317
063e05be 318SCM_PROC (s_fileno, "fileno", 1, 0, 0, scm_fileno);
1cc91f1b 319
0f2d19dd 320SCM
063e05be 321scm_fileno (port)
0f2d19dd 322 SCM port;
0f2d19dd
JB
323{
324 int fd;
063e05be 325 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_fileno);
0f2d19dd 326 fd = fileno ((FILE *)SCM_STREAM (port));
02b754d3 327 if (fd == -1)
063e05be 328 scm_syserror (s_fileno);
02b754d3 329 return SCM_MAKINUM (fd);
0f2d19dd
JB
330}
331
063e05be 332SCM_PROC (s_isatty, "isatty?", 1, 0, 0, scm_isatty_p);
1cc91f1b 333
0f2d19dd 334SCM
063e05be 335scm_isatty_p (port)
0f2d19dd 336 SCM port;
0f2d19dd
JB
337{
338 int rv;
063e05be 339 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_isatty);
0f2d19dd
JB
340 rv = fileno ((FILE *)SCM_STREAM (port));
341 if (rv == -1)
063e05be 342 scm_syserror (s_isatty);
02b754d3
GH
343 rv = isatty (rv);
344 return rv ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
345}
346
347
348
063e05be 349SCM_PROC (s_fdopen, "fdopen", 2, 0, 0, scm_fdopen);
1cc91f1b 350
0f2d19dd 351SCM
063e05be 352scm_fdopen (fdes, modes)
0f2d19dd
JB
353 SCM fdes;
354 SCM modes;
0f2d19dd
JB
355{
356 FILE *f;
357 SCM port;
8b13c6b3 358 struct scm_port_table * pt;
0f2d19dd 359
063e05be 360 SCM_ASSERT (SCM_INUMP (fdes), fdes, SCM_ARG1, s_fdopen);
ae2fa5bc
GH
361 SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2,
362 s_fdopen);
89958ad0 363 SCM_COERCE_SUBSTR (modes);
8b13c6b3 364 SCM_NEWCELL (port);
0f2d19dd 365 SCM_DEFER_INTS;
ae2fa5bc 366 f = fdopen (SCM_INUM (fdes), SCM_ROCHARS (modes));
0f2d19dd 367 if (f == NULL)
063e05be 368 scm_syserror (s_fdopen);
8b13c6b3
GH
369 pt = scm_add_to_port_table (port);
370 SCM_SETPTAB_ENTRY (port, pt);
ae2fa5bc 371 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
e38303a2 372 SCM_SETSTREAM (port, (SCM)f);
898a256f 373 if (SCM_BUF0 & SCM_CAR (port))
8b13c6b3 374 scm_setbuf0 (port);
0f2d19dd
JB
375 SCM_ALLOW_INTS;
376 return port;
377}
378
379
380
381/* Move a port's underlying file descriptor to a given value.
8b13c6b3
GH
382 * Returns #f if fdes is already the given value.
383 * #t if fdes moved.
0f2d19dd
JB
384 * MOVE->FDES is implemented in Scheme and calls this primitive.
385 */
063e05be 386SCM_PROC (s_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0, scm_primitive_move_to_fdes);
1cc91f1b 387
0f2d19dd 388SCM
063e05be 389scm_primitive_move_to_fdes (port, fd)
0f2d19dd
JB
390 SCM port;
391 SCM fd;
0f2d19dd
JB
392{
393 FILE *stream;
394 int old_fd;
395 int new_fd;
396 int rv;
397
063e05be
GH
398 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_primitive_move_to_fdes);
399 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG2, s_primitive_move_to_fdes);
0f2d19dd
JB
400 SCM_DEFER_INTS;
401 stream = (FILE *)SCM_STREAM (port);
402 old_fd = fileno (stream);
403 new_fd = SCM_INUM (fd);
404 if (old_fd == new_fd)
405 {
406 SCM_ALLOW_INTS;
8b13c6b3 407 return SCM_BOOL_F;
0f2d19dd
JB
408 }
409 scm_evict_ports (new_fd);
410 rv = dup2 (old_fd, new_fd);
411 if (rv == -1)
063e05be 412 scm_syserror (s_primitive_move_to_fdes);
0f2d19dd
JB
413 scm_setfileno (stream, new_fd);
414 SCM_SYSCALL (close (old_fd));
415 SCM_ALLOW_INTS;
8b13c6b3 416 return SCM_BOOL_T;
0f2d19dd
JB
417}
418
67ec3667
GH
419#ifdef FD_SETTER
420#define SET_FILE_FD_FIELD(F,D) ((F)->FD_SETTER = (D))
421#endif
1cc91f1b 422
0f2d19dd
JB
423void
424scm_setfileno (fs, fd)
425 FILE *fs;
426 int fd;
0f2d19dd
JB
427{
428#ifdef SET_FILE_FD_FIELD
429 SET_FILE_FD_FIELD(fs, fd);
430#else
4edc089c
GH
431 scm_misc_error ("scm_setfileno", "Not fully implemented on this platform",
432 SCM_EOL);
0f2d19dd
JB
433#endif
434}
435
0f2d19dd
JB
436/* Return a list of ports using a given file descriptor. */
437SCM_PROC(s_fdes_to_ports, "fdes->ports", 1, 0, 0, scm_fdes_to_ports);
1cc91f1b 438
0f2d19dd
JB
439SCM
440scm_fdes_to_ports (fd)
441 SCM fd;
0f2d19dd
JB
442{
443 SCM result = SCM_EOL;
444 int int_fd;
445 int i;
446
447 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG1, s_fdes_to_ports);
448 int_fd = SCM_INUM (fd);
449
450 SCM_DEFER_INTS;
451 for (i = 0; i < scm_port_table_size; i++)
452 {
453 if (SCM_FPORTP (scm_port_table[i]->port)
454 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == int_fd)
455 result = scm_cons (scm_port_table[i]->port, result);
456 }
457 SCM_ALLOW_INTS;
458 return result;
459}
460
1cc91f1b 461
0f2d19dd
JB
462void
463scm_init_ioext ()
0f2d19dd
JB
464{
465 /* fseek() symbols. */
466 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
467 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
468 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
469
0f2d19dd
JB
470#include "ioext.x"
471}
472