* boot-9.scm (netent:addrtype, servent:port): added missing
[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
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
40 */
41\f
42
43
44#include <stdio.h>
0f2d19dd
JB
45#include "fd.h"
46#include "_scm.h"
1146b6cd
GH
47#include "genio.h"
48#include "read.h"
20e6290e 49#include "fports.h"
1146b6cd
GH
50#include "unif.h"
51#include "chars.h"
20e6290e
JB
52
53#include "ioext.h"
0f2d19dd 54
95b88819
GH
55#ifdef HAVE_STRING_H
56#include <string.h>
57#endif
58#ifdef HAVE_UNISTD_H
59#include <unistd.h>
60#endif
0f2d19dd
JB
61\f
62
1146b6cd
GH
63SCM_PROC (s_read_delimited_x, "%read-delimited!", 3, 3, 0, scm_read_delimited_x);
64
65SCM
66scm_read_delimited_x (delims, buf, gobble, port, start, end)
67 SCM delims;
68 SCM buf;
69 SCM gobble;
70 SCM port;
71 SCM start;
72 SCM end;
73{
74 long j;
75 char *cbuf;
76 long cstart;
77 long cend;
78 int c;
79 char *cdelims;
80 int num_delims;
81
ae2fa5bc 82 SCM_ASSERT (SCM_NIMP (delims) && SCM_ROSTRINGP (delims),
1146b6cd 83 delims, SCM_ARG1, s_read_delimited_x);
ae2fa5bc
GH
84 cdelims = SCM_ROCHARS (delims);
85 num_delims = SCM_ROLENGTH (delims);
1146b6cd
GH
86 SCM_ASSERT (SCM_NIMP (buf) && SCM_STRINGP (buf),
87 buf, SCM_ARG2, s_read_delimited_x);
88 cbuf = SCM_CHARS (buf);
89 cend = SCM_LENGTH (buf);
90 if (SCM_UNBNDP (port))
91 port = scm_cur_inp;
92 else
93 {
94 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port),
95 port, SCM_ARG1, s_read_delimited_x);
96 }
97
98 if (SCM_UNBNDP (start))
99 cstart = 0;
100 else
101 {
102 cstart = scm_num2long (start,
103 (char *) SCM_ARG5, s_read_delimited_x);
104 if (cstart < 0 || cstart >= cend)
105 scm_out_of_range (s_read_delimited_x, start);
106
107 if (!SCM_UNBNDP (end))
108 {
109 long tend = scm_num2long (end, (char *) SCM_ARG6,
110 s_read_delimited_x);
111 if (tend <= cstart || tend > cend)
112 scm_out_of_range (s_read_delimited_x, end);
113 cend = tend;
114 }
115 }
116
117 for (j = cstart; j < cend; j++)
118 {
119 int k;
120
121 c = scm_gen_getc (port);
122 for (k = 0; k < num_delims; k++)
123 {
124 if (cdelims[k] == c)
125 {
126 if (SCM_FALSEP (gobble))
127 scm_gen_ungetc (c, port);
128
129 return scm_cons (SCM_MAKICHR (c),
130 scm_long2num (j - cstart));
131 }
132 }
133 if (c == EOF)
134 return scm_cons (SCM_EOF_VAL,
135 scm_long2num (j - cstart));
136
137 cbuf[j] = c;
138 }
139 return scm_cons (SCM_BOOL_F, scm_long2num (j - cstart));
140}
141
142SCM_PROC (s_write_line, "write-line", 1, 1, 0, scm_write_line);
143
144SCM
145scm_write_line (obj, port)
146 SCM obj;
147 SCM port;
148{
149 scm_display (obj, port);
150 return scm_newline (port);
151}
152
063e05be 153SCM_PROC (s_ftell, "ftell", 1, 0, 0, scm_ftell);
1cc91f1b 154
0f2d19dd 155SCM
063e05be 156scm_ftell (port)
0f2d19dd 157 SCM port;
0f2d19dd
JB
158{
159 long pos;
063e05be 160 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_ftell);
0f2d19dd
JB
161 SCM_SYSCALL (pos = ftell ((FILE *)SCM_STREAM (port)));
162 if (pos < 0)
063e05be 163 scm_syserror (s_ftell);
0f2d19dd
JB
164 if (pos > 0 && SCM_CRDYP (port))
165 pos--;
8588fa12 166 return scm_long2num (pos);
0f2d19dd
JB
167}
168
169
170
063e05be 171SCM_PROC (s_fseek, "fseek", 3, 0, 0, scm_fseek);
1cc91f1b 172
0f2d19dd 173SCM
063e05be 174scm_fseek (port, offset, whence)
0f2d19dd
JB
175 SCM port;
176 SCM offset;
177 SCM whence;
0f2d19dd
JB
178{
179 int rv;
8588fa12
GH
180 long loff;
181
063e05be
GH
182 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_fseek);
183 loff = scm_num2long (offset, (char *)SCM_ARG2, s_fseek);
0f2d19dd 184 SCM_ASSERT (SCM_INUMP (whence) && (SCM_INUM (whence) < 3) && (SCM_INUM (whence) >= 0),
063e05be 185 whence, SCM_ARG3, s_fseek);
8588fa12 186
0f2d19dd
JB
187 SCM_CLRDY (port); /* Clear ungetted char */
188 /* Values of whence are interned in scm_init_ioext. */
8588fa12 189 rv = fseek ((FILE *)SCM_STREAM (port), loff, SCM_INUM (whence));
02b754d3 190 if (rv != 0)
063e05be 191 scm_syserror (s_fseek);
02b754d3 192 return SCM_UNSPECIFIED;
0f2d19dd
JB
193}
194
195
196
063e05be 197SCM_PROC (s_freopen, "freopen", 3, 0, 0, scm_freopen);
1cc91f1b 198
0f2d19dd 199SCM
063e05be 200scm_freopen (filename, modes, port)
0f2d19dd
JB
201 SCM filename;
202 SCM modes;
203 SCM port;
0f2d19dd
JB
204{
205 FILE *f;
ae2fa5bc
GH
206 SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename,
207 SCM_ARG1, s_freopen);
208 SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2,
209 s_freopen);
0f2d19dd 210 SCM_DEFER_INTS;
063e05be 211 SCM_ASSERT (SCM_NIMP (port) && SCM_FPORTP (port), port, SCM_ARG3, s_freopen);
ae2fa5bc
GH
212 SCM_SYSCALL (f = freopen (SCM_ROCHARS (filename), SCM_ROCHARS (modes),
213 (FILE *)SCM_STREAM (port)));
0f2d19dd
JB
214 if (!f)
215 {
216 SCM p;
217 p = port;
218 port = SCM_MAKINUM (errno);
898a256f 219 SCM_SETAND_CAR (p, ~SCM_OPN);
0f2d19dd
JB
220 scm_remove_from_port_table (p);
221 }
222 else
223 {
ae2fa5bc 224 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
0f2d19dd 225 SCM_SETSTREAM (port, (SCM)f);
ae2fa5bc 226 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
898a256f 227 if (SCM_BUF0 & SCM_CAR (port))
0f2d19dd
JB
228 scm_setbuf0 (port);
229 }
230 SCM_ALLOW_INTS;
231 return port;
232}
233
234
235
063e05be 236SCM_PROC (s_duplicate_port, "duplicate-port", 2, 0, 0, scm_duplicate_port);
1cc91f1b 237
0f2d19dd 238SCM
063e05be 239scm_duplicate_port (oldpt, modes)
0f2d19dd
JB
240 SCM oldpt;
241 SCM modes;
0f2d19dd
JB
242{
243 int oldfd;
244 int newfd;
245 FILE *f;
246 SCM newpt;
ae2fa5bc
GH
247 SCM_ASSERT (SCM_NIMP (oldpt) && SCM_OPPORTP (oldpt), oldpt, SCM_ARG1,
248 s_duplicate_port);
249 SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2,
250 s_duplicate_port);
0f2d19dd
JB
251 SCM_NEWCELL (newpt);
252 SCM_DEFER_INTS;
253 oldfd = fileno ((FILE *)SCM_STREAM (oldpt));
254 if (oldfd == -1)
063e05be 255 scm_syserror (s_duplicate_port);
0f2d19dd
JB
256 SCM_SYSCALL (newfd = dup (oldfd));
257 if (newfd == -1)
063e05be 258 scm_syserror (s_duplicate_port);
ae2fa5bc 259 f = fdopen (newfd, SCM_ROCHARS (modes));
0f2d19dd
JB
260 if (!f)
261 {
262 SCM_SYSCALL (close (newfd));
063e05be 263 scm_syserror (s_duplicate_port);
0f2d19dd
JB
264 }
265 {
266 struct scm_port_table * pt;
267 pt = scm_add_to_port_table (newpt);
268 SCM_SETPTAB_ENTRY (newpt, pt);
ae2fa5bc 269 SCM_SETCAR (newpt, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
898a256f 270 if (SCM_BUF0 & SCM_CAR (newpt))
0f2d19dd
JB
271 scm_setbuf0 (newpt);
272 SCM_SETSTREAM (newpt, (SCM)f);
ebf7394e 273 SCM_PTAB_ENTRY (newpt)->file_name = SCM_PTAB_ENTRY (oldpt)->file_name;
0f2d19dd
JB
274 }
275 SCM_ALLOW_INTS;
276 return newpt;
277}
278
279
280
063e05be 281SCM_PROC (s_redirect_port, "redirect-port", 2, 0, 0, scm_redirect_port);
1cc91f1b 282
0f2d19dd 283SCM
063e05be 284scm_redirect_port (into_pt, from_pt)
0f2d19dd
JB
285 SCM into_pt;
286 SCM from_pt;
0f2d19dd
JB
287{
288 int ans, oldfd, newfd;
289 SCM_DEFER_INTS;
063e05be
GH
290 SCM_ASSERT (SCM_NIMP (into_pt) && SCM_OPPORTP (into_pt), into_pt, SCM_ARG1, s_redirect_port);
291 SCM_ASSERT (SCM_NIMP (from_pt) && SCM_OPPORTP (from_pt), from_pt, SCM_ARG2, s_redirect_port);
0f2d19dd 292 oldfd = fileno ((FILE *)SCM_STREAM (into_pt));
02b754d3 293 if (oldfd == -1)
063e05be 294 scm_syserror (s_redirect_port);
0f2d19dd 295 newfd = fileno ((FILE *)SCM_STREAM (from_pt));
02b754d3 296 if (newfd == -1)
063e05be 297 scm_syserror (s_redirect_port);
02b754d3
GH
298 SCM_SYSCALL (ans = dup2 (oldfd, newfd));
299 if (ans == -1)
063e05be 300 scm_syserror (s_redirect_port);
0f2d19dd 301 SCM_ALLOW_INTS;
02b754d3 302 return SCM_UNSPECIFIED;
0f2d19dd
JB
303}
304
063e05be 305SCM_PROC (s_fileno, "fileno", 1, 0, 0, scm_fileno);
1cc91f1b 306
0f2d19dd 307SCM
063e05be 308scm_fileno (port)
0f2d19dd 309 SCM port;
0f2d19dd
JB
310{
311 int fd;
063e05be 312 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_fileno);
0f2d19dd 313 fd = fileno ((FILE *)SCM_STREAM (port));
02b754d3 314 if (fd == -1)
063e05be 315 scm_syserror (s_fileno);
02b754d3 316 return SCM_MAKINUM (fd);
0f2d19dd
JB
317}
318
063e05be 319SCM_PROC (s_isatty, "isatty?", 1, 0, 0, scm_isatty_p);
1cc91f1b 320
0f2d19dd 321SCM
063e05be 322scm_isatty_p (port)
0f2d19dd 323 SCM port;
0f2d19dd
JB
324{
325 int rv;
063e05be 326 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_isatty);
0f2d19dd
JB
327 rv = fileno ((FILE *)SCM_STREAM (port));
328 if (rv == -1)
063e05be 329 scm_syserror (s_isatty);
02b754d3
GH
330 rv = isatty (rv);
331 return rv ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
332}
333
334
335
063e05be 336SCM_PROC (s_fdopen, "fdopen", 2, 0, 0, scm_fdopen);
1cc91f1b 337
0f2d19dd 338SCM
063e05be 339scm_fdopen (fdes, modes)
0f2d19dd
JB
340 SCM fdes;
341 SCM modes;
0f2d19dd
JB
342{
343 FILE *f;
344 SCM port;
8b13c6b3 345 struct scm_port_table * pt;
0f2d19dd 346
063e05be 347 SCM_ASSERT (SCM_INUMP (fdes), fdes, SCM_ARG1, s_fdopen);
ae2fa5bc
GH
348 SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2,
349 s_fdopen);
8b13c6b3 350 SCM_NEWCELL (port);
0f2d19dd 351 SCM_DEFER_INTS;
ae2fa5bc 352 f = fdopen (SCM_INUM (fdes), SCM_ROCHARS (modes));
0f2d19dd 353 if (f == NULL)
063e05be 354 scm_syserror (s_fdopen);
8b13c6b3
GH
355 pt = scm_add_to_port_table (port);
356 SCM_SETPTAB_ENTRY (port, pt);
ae2fa5bc 357 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (SCM_ROCHARS (modes)));
898a256f 358 if (SCM_BUF0 & SCM_CAR (port))
8b13c6b3
GH
359 scm_setbuf0 (port);
360 SCM_SETSTREAM (port, (SCM)f);
0f2d19dd
JB
361 SCM_ALLOW_INTS;
362 return port;
363}
364
365
366
367/* Move a port's underlying file descriptor to a given value.
8b13c6b3
GH
368 * Returns #f if fdes is already the given value.
369 * #t if fdes moved.
0f2d19dd
JB
370 * MOVE->FDES is implemented in Scheme and calls this primitive.
371 */
063e05be 372SCM_PROC (s_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0, scm_primitive_move_to_fdes);
1cc91f1b 373
0f2d19dd 374SCM
063e05be 375scm_primitive_move_to_fdes (port, fd)
0f2d19dd
JB
376 SCM port;
377 SCM fd;
0f2d19dd
JB
378{
379 FILE *stream;
380 int old_fd;
381 int new_fd;
382 int rv;
383
063e05be
GH
384 SCM_ASSERT (SCM_NIMP (port) && SCM_OPFPORTP (port), port, SCM_ARG1, s_primitive_move_to_fdes);
385 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG2, s_primitive_move_to_fdes);
0f2d19dd
JB
386 SCM_DEFER_INTS;
387 stream = (FILE *)SCM_STREAM (port);
388 old_fd = fileno (stream);
389 new_fd = SCM_INUM (fd);
390 if (old_fd == new_fd)
391 {
392 SCM_ALLOW_INTS;
8b13c6b3 393 return SCM_BOOL_F;
0f2d19dd
JB
394 }
395 scm_evict_ports (new_fd);
396 rv = dup2 (old_fd, new_fd);
397 if (rv == -1)
063e05be 398 scm_syserror (s_primitive_move_to_fdes);
0f2d19dd
JB
399 scm_setfileno (stream, new_fd);
400 SCM_SYSCALL (close (old_fd));
401 SCM_ALLOW_INTS;
8b13c6b3 402 return SCM_BOOL_T;
0f2d19dd
JB
403}
404
1cc91f1b 405
0f2d19dd
JB
406void
407scm_setfileno (fs, fd)
408 FILE *fs;
409 int fd;
0f2d19dd
JB
410{
411#ifdef SET_FILE_FD_FIELD
412 SET_FILE_FD_FIELD(fs, fd);
413#else
414 Configure could not guess the name of the correct field in a FILE *.
415
416 This function needs to be ported to your system.
417
418 SET_FILE_FD_FIELD should change the descriptor refered to by a stdio
419 stream, and nothing else.
420
421 The way to port this file is to add cases to configure.in. Search
422 that file for "SET_FILE_FD_FIELD" and follow the examples there.
423#endif
424}
425
426/* Move ports with the specified file descriptor to new descriptors,
427 * reseting the revealed count to 0.
428 * Should be called with SCM_DEFER_INTS active.
429 */
1cc91f1b 430
0f2d19dd
JB
431void
432scm_evict_ports (fd)
433 int fd;
0f2d19dd
JB
434{
435 int i;
436
437 for (i = 0; i < scm_port_table_size; i++)
438 {
439 if (SCM_FPORTP (scm_port_table[i]->port)
440 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == fd)
441 {
442 scm_setfileno ((FILE *)SCM_STREAM (scm_port_table[i]->port), dup (fd));
443 scm_set_port_revealed_x (scm_port_table[i]->port, SCM_MAKINUM (0));
444 }
445 }
446}
447
448/* Return a list of ports using a given file descriptor. */
449SCM_PROC(s_fdes_to_ports, "fdes->ports", 1, 0, 0, scm_fdes_to_ports);
1cc91f1b 450
0f2d19dd
JB
451SCM
452scm_fdes_to_ports (fd)
453 SCM fd;
0f2d19dd
JB
454{
455 SCM result = SCM_EOL;
456 int int_fd;
457 int i;
458
459 SCM_ASSERT (SCM_INUMP (fd), fd, SCM_ARG1, s_fdes_to_ports);
460 int_fd = SCM_INUM (fd);
461
462 SCM_DEFER_INTS;
463 for (i = 0; i < scm_port_table_size; i++)
464 {
465 if (SCM_FPORTP (scm_port_table[i]->port)
466 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == int_fd)
467 result = scm_cons (scm_port_table[i]->port, result);
468 }
469 SCM_ALLOW_INTS;
470 return result;
471}
472
1cc91f1b 473
0f2d19dd
JB
474void
475scm_init_ioext ()
0f2d19dd
JB
476{
477 /* fseek() symbols. */
478 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
479 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
480 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
481
0f2d19dd
JB
482#include "ioext.x"
483}
484