*** empty log message ***
[bpt/guile.git] / libguile / fports.c
CommitLineData
3d8d56df 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#include <stdio.h>
44#include "_scm.h"
20e6290e
JB
45#include "markers.h"
46
47#include "fports.h"
95b88819
GH
48
49#ifdef HAVE_STRING_H
50#include <string.h>
51#endif
0f2d19dd
JB
52#ifdef HAVE_UNISTD_H
53#include <unistd.h>
54#else
0f2d19dd
JB
55scm_sizet fwrite ();
56#endif
0f2d19dd
JB
57
58
59#ifdef __IBMC__
60#include <io.h>
61#include <direct.h>
0f2d19dd
JB
62#else
63#ifndef MSDOS
64#ifndef ultrix
65#ifndef vms
66#ifdef _DCC
67#include <ioctl.h>
68#define setbuf(stream, buf) setvbuf(stream, buf, _IONBF, 0)
69#else
70#ifdef MWC
71#include <sys/io.h>
72#else
73#ifndef THINK_C
74#ifndef ARM_ULIB
75#include <sys/ioctl.h>
76#endif
77#endif
78#endif
79#endif
80#endif
81#endif
82#endif
83#endif
84\f
85
86/* {Ports - file ports}
87 *
88 */
89
90/* should be called with SCM_DEFER_INTS active */
1717856b 91
0f2d19dd
JB
92SCM
93scm_setbuf0 (port)
94 SCM port;
0f2d19dd
JB
95{
96#ifndef NOSETBUF
97#ifndef MSDOS
0f2d19dd
JB
98#ifndef ultrix
99 SCM_SYSCALL (setbuf ((FILE *)SCM_STREAM (port), 0););
100#endif
101#endif
0f2d19dd
JB
102#endif
103 return SCM_UNSPECIFIED;
104}
105
eadd48de
GH
106/* Move ports with the specified file descriptor to new descriptors,
107 * reseting the revealed count to 0.
108 * Should be called with SCM_DEFER_INTS active.
0f2d19dd 109 */
1717856b 110
eadd48de
GH
111void
112scm_evict_ports (fd)
113 int fd;
0f2d19dd 114{
eadd48de 115 int i;
0f2d19dd 116
eadd48de
GH
117 for (i = 0; i < scm_port_table_size; i++)
118 {
119 if (SCM_FPORTP (scm_port_table[i]->port)
120 && fileno ((FILE *)SCM_STREAM (scm_port_table[i]->port)) == fd)
121 {
122 scm_setfileno ((FILE *)SCM_STREAM (scm_port_table[i]->port), dup (fd));
123 scm_set_port_revealed_x (scm_port_table[i]->port, SCM_MAKINUM (0));
124 }
125 }
126}
0f2d19dd
JB
127
128/* scm_open_file
129 * Return a new port open on a given file.
130 *
131 * The mode string must match the pattern: [rwa+]** which
132 * is interpreted in the usual unix way.
133 *
134 * Return the new port.
135 */
19639113 136SCM_PROC(s_open_file, "open-file", 2, 0, 0, scm_open_file);
1717856b 137
0f2d19dd 138SCM
19639113
GH
139scm_open_file (filename, modes)
140 SCM filename;
141 SCM modes;
0f2d19dd 142{
19639113 143 SCM port;
0f2d19dd 144 FILE *f;
19639113
GH
145 char *file;
146 char *mode;
147
148 SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename, SCM_ARG1, s_open_file);
149 SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2, s_open_file);
150 if (SCM_SUBSTRP (filename))
151 filename = scm_makfromstr (SCM_ROCHARS (filename), SCM_ROLENGTH (filename), 0);
152 if (SCM_SUBSTRP (modes))
153 modes = scm_makfromstr (SCM_ROCHARS (modes), SCM_ROLENGTH (modes), 0);
154
155 file = SCM_ROCHARS (filename);
156 mode = SCM_ROCHARS (modes);
157
0f2d19dd
JB
158 SCM_NEWCELL (port);
159 SCM_DEFER_INTS;
19639113 160 SCM_SYSCALL (f = fopen (file, mode));
0f2d19dd
JB
161 if (!f)
162 {
3d8d56df
GH
163 int en = errno;
164
f5bf2977 165 scm_syserror_msg (s_open_file, "%s: %S",
19639113
GH
166 scm_listify (scm_makfrom0str (strerror (errno)),
167 filename,
3d8d56df
GH
168 SCM_UNDEFINED),
169 en);
0f2d19dd
JB
170 }
171 else
172 {
173 struct scm_port_table * pt;
19639113 174
0f2d19dd
JB
175 pt = scm_add_to_port_table (port);
176 SCM_SETPTAB_ENTRY (port, pt);
a6c64c3c 177 SCM_SETCAR (port, scm_tc16_fport | scm_mode_bits (mode));
7471fb03 178 SCM_SETSTREAM (port, (SCM) f);
a6c64c3c 179 if (SCM_BUF0 & SCM_CAR (port))
0f2d19dd 180 scm_setbuf0 (port);
96937708 181 SCM_PTAB_ENTRY (port)->file_name = filename;
0f2d19dd 182 }
19639113 183 SCM_ALLOW_INTS;
0f2d19dd
JB
184 return port;
185}
186
a089567e
JB
187
188/* Build a Scheme port from an open stdio port, FILE.
189 MODE indicates whether FILE is open for reading or writing; it uses
190 the same notation as open-file's second argument.
191 If NAME is non-zero, use it as the port's filename.
192
193 scm_stdio_to_port sets the revealed count for FILE's file
194 descriptor to 1, so that FILE won't be closed when the port object
195 is GC'd. */
196SCM
197scm_stdio_to_port (file, mode, name)
198 FILE *file;
199 char *mode;
200 char *name;
201{
202 long mode_bits = scm_mode_bits (mode);
203 SCM port;
204 struct scm_port_table * pt;
205
206 SCM_NEWCELL (port);
207 SCM_DEFER_INTS;
208 {
209 pt = scm_add_to_port_table (port);
210 SCM_SETPTAB_ENTRY (port, pt);
211 SCM_SETCAR (port, (scm_tc16_fport | mode_bits));
7471fb03 212 SCM_SETSTREAM (port, (SCM) file);
a089567e
JB
213 if (SCM_BUF0 & SCM_CAR (port))
214 scm_setbuf0 (port);
a089567e
JB
215 SCM_PTAB_ENTRY (port)->file_name = scm_makfrom0str (name);
216 }
217 SCM_ALLOW_INTS;
218 scm_set_port_revealed_x (port, SCM_MAKINUM (1));
219 return port;
220}
221
222
1717856b
JB
223
224static int prinfport SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
225
0f2d19dd 226static int
1717856b 227prinfport (exp, port, pstate)
0f2d19dd
JB
228 SCM exp;
229 SCM port;
1717856b 230 scm_print_state *pstate;
0f2d19dd
JB
231{
232 SCM name;
233 char * c;
234 if (SCM_CLOSEDP (exp))
235 {
236 c = "file";
237 }
238 else
239 {
240 name = SCM_PTAB_ENTRY (exp)->file_name;
241 if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
242 c = SCM_ROCHARS (name);
243 else
244 c = "file";
245 }
19639113 246
0f2d19dd
JB
247 scm_prinport (exp, port, c);
248 return !0;
249}
250
251
1717856b
JB
252
253static int scm_fgetc SCM_P ((FILE * s));
254
0f2d19dd
JB
255static int
256scm_fgetc (s)
257 FILE * s;
0f2d19dd
JB
258{
259 if (feof (s))
260 return EOF;
261 else
262 return fgetc (s);
263}
264
3cb988bd
TP
265/*
266 * The fgets method must take a port as its argument, rather than
267 * the underlying file handle. The reason is that we also provide
268 * a generic fgets method for ports which can't use fgets(3) (e.g.
269 * string ports). This generic method calls the port's own
270 * fgetc method. In order for it to know how to get that method,
271 * we must pass the original Scheme port object.
272 */
273
274static char * scm_fgets SCM_P ((SCM port));
275
276static char *
277scm_fgets (port)
278 SCM port;
279{
280 FILE *f;
281
282 char *buf = NULL;
283 char *p; /* pointer to current buffer position */
284 int i = 0; /* index into current buffer position */
285 int limit = 80; /* current size of buffer */
286 int lp;
287
288 f = SCM_STREAM (port);
289 if (feof (f))
290 return NULL;
291
292 buf = (char *) scm_must_malloc (limit * sizeof(char), "fgets");
293
294 while (1) {
295 p = buf + i;
296 if (fgets (p, limit - i, f) == NULL) {
297 if (i)
298 return buf;
299 scm_must_free (buf);
300 return NULL;
301 }
302
303 if (strlen(p) < limit - i - 1)
304 return buf;
305
306 buf = (char *) scm_must_realloc (buf,
307 sizeof(char) * limit,
308 sizeof(char) * limit * 2,
309 "fgets");
310
311 i = limit - 1;
312 limit *= 2;
313 }
314}
315
0f2d19dd 316#ifdef vms
1717856b
JB
317
318static scm_sizet pwrite SCM_P ((char *ptr, scm_sizet size, nitems, FILE *port));
319
0f2d19dd
JB
320static scm_sizet
321pwrite (ptr, size, nitems, port)
322 char *ptr;
323 scm_sizet size, nitems;
324 FILE *port;
0f2d19dd
JB
325{
326 scm_sizet len = size * nitems;
327 scm_sizet i = 0;
328 for (; i < len; i++)
329 putc (ptr[i], port);
330 return len;
331}
332
333#define ffwrite pwrite
334#else
335#define ffwrite fwrite
336#endif
337
338\f
339/* This otherwise pointless code helps some poor
340 * crippled C compilers cope with life.
341 */
1717856b
JB
342
343static int local_fclose SCM_P ((FILE *fp));
344
0f2d19dd
JB
345static int
346local_fclose (fp)
347 FILE * fp;
348{
349 return fclose (fp);
350}
351
1717856b
JB
352static int local_fflush SCM_P ((FILE *fp));
353
0f2d19dd
JB
354static int
355local_fflush (fp)
356 FILE * fp;
357{
358 return fflush (fp);
359}
360
1717856b
JB
361static int local_fputc SCM_P ((int c, FILE *fp));
362
0f2d19dd
JB
363static int
364local_fputc (c, fp)
365 int c;
366 FILE * fp;
367{
368 return fputc (c, fp);
369}
370
1717856b
JB
371static int local_fputs SCM_P ((char *s, FILE *fp));
372
0f2d19dd
JB
373static int
374local_fputs (s, fp)
375 char * s;
376 FILE * fp;
377{
378 return fputs (s, fp);
379}
380
1717856b
JB
381static scm_sizet local_ffwrite SCM_P ((void *ptr, int size, int nitems, FILE *fp));
382
0f2d19dd
JB
383static scm_sizet
384local_ffwrite (ptr, size, nitems, fp)
385 void * ptr;
386 int size;
387 int nitems;
388 FILE * fp;
389{
390 return ffwrite (ptr, size, nitems, fp);
391}
392
8f29fbd0
JB
393static int
394print_pipe_port (SCM exp, SCM port, scm_print_state *pstate)
395{
396 scm_prinport (exp, port, "pipe");
397 return 1;
398}
399
400
401
6a2c4c81
JB
402/* On SunOS, there's no declaration for pclose in the headers, so
403 putting it directly in the initializer for scm_pipob doesn't really
404 fly. We could add an extern declaration for it, but then it'll
405 mismatch on some systems that do have a declaration. So we just
406 wrap it up this way. */
407static int
408local_pclose (fp)
409 FILE * fp;
410{
411 return pclose (fp);
412}
413
0f2d19dd
JB
414\f
415scm_ptobfuns scm_fptob =
416{
417 scm_mark0,
1717856b 418 (int (*) SCM_P ((SCM))) local_fclose,
0f2d19dd
JB
419 prinfport,
420 0,
1717856b
JB
421 (int (*) SCM_P ((int, SCM))) local_fputc,
422 (int (*) SCM_P ((char *, SCM))) local_fputs,
423 (scm_sizet (*) SCM_P ((char *, scm_sizet, scm_sizet, SCM))) local_ffwrite,
424 (int (*) SCM_P ((SCM))) local_fflush,
425 (int (*) SCM_P ((SCM))) scm_fgetc,
3cb988bd 426 (char * (*) SCM_P ((SCM))) scm_fgets,
1717856b 427 (int (*) SCM_P ((SCM))) local_fclose
0f2d19dd
JB
428};
429
6a2c4c81 430/* {Pipe ports} */
0f2d19dd
JB
431scm_ptobfuns scm_pipob =
432{
433 scm_mark0,
6a2c4c81 434 (int (*) SCM_P ((SCM))) local_pclose,
8f29fbd0 435 print_pipe_port,
0f2d19dd 436 0,
1717856b
JB
437 (int (*) SCM_P ((int, SCM))) local_fputc,
438 (int (*) SCM_P ((char *, SCM))) local_fputs,
439 (scm_sizet (*) SCM_P ((char *, scm_sizet, scm_sizet, SCM))) local_ffwrite,
440 (int (*) SCM_P ((SCM))) local_fflush,
441 (int (*) SCM_P ((SCM))) scm_fgetc,
3cb988bd 442 (char * (*) SCM_P ((SCM))) scm_fgets,
6a2c4c81 443 (int (*) SCM_P ((SCM))) local_pclose
19468eff 444};
0f2d19dd 445
0f2d19dd
JB
446void
447scm_init_fports ()
0f2d19dd
JB
448{
449#include "fports.x"
450}