* Makefile.in: Rebuilt.
[bpt/guile.git] / libguile / ports.c
CommitLineData
1e598865 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#include <stdio.h>
43#include "_scm.h"
20e6290e
JB
44#include "genio.h"
45#include "chars.h"
0f2d19dd 46
20e6290e 47#include "markers.h"
5d09ff4e 48#include "filesys.h"
20e6290e
JB
49#include "fports.h"
50#include "strports.h"
51#include "vports.h"
89ea5b7c 52#include "kw.h"
20e6290e
JB
53
54#include "ports.h"
0f2d19dd
JB
55
56#ifdef HAVE_MALLOC_H
95b88819 57#include <malloc.h>
0f2d19dd
JB
58#endif
59
60#ifdef HAVE_UNISTD_H
61#include <unistd.h>
62#endif
63
95b88819
GH
64#ifdef HAVE_SYS_IOCTL_H
65#include <sys/ioctl.h>
66#endif
0f2d19dd
JB
67\f
68
69
70/* scm_ptobs scm_numptob
71 * implement a dynamicly resized array of ptob records.
72 * Indexes into this table are used when generating type
73 * tags for smobjects (if you know a tag you can get an index and conversely).
74 */
75scm_ptobfuns *scm_ptobs;
76scm_sizet scm_numptob;
77
1cc91f1b 78
0f2d19dd
JB
79SCM
80scm_markstream (ptr)
81 SCM ptr;
0f2d19dd
JB
82{
83 int openp;
84 if (SCM_GC8MARKP (ptr))
85 return SCM_BOOL_F;
86 openp = SCM_CAR (ptr) & SCM_OPN;
87 SCM_SETGC8MARK (ptr);
88 if (openp)
89 return SCM_STREAM (ptr);
90 else
91 return SCM_BOOL_F;
92}
93
94
1cc91f1b 95
0f2d19dd
JB
96long
97scm_newptob (ptob)
98 scm_ptobfuns *ptob;
0f2d19dd
JB
99{
100 char *tmp;
101 if (255 <= scm_numptob)
102 goto ptoberr;
103 SCM_DEFER_INTS;
104 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs, (1 + scm_numptob) * sizeof (scm_ptobfuns)));
105 if (tmp)
106 {
107 scm_ptobs = (scm_ptobfuns *) tmp;
108 scm_ptobs[scm_numptob].mark = ptob->mark;
109 scm_ptobs[scm_numptob].free = ptob->free;
110 scm_ptobs[scm_numptob].print = ptob->print;
111 scm_ptobs[scm_numptob].equalp = ptob->equalp;
112 scm_ptobs[scm_numptob].fputc = ptob->fputc;
113 scm_ptobs[scm_numptob].fputs = ptob->fputs;
114 scm_ptobs[scm_numptob].fwrite = ptob->fwrite;
115 scm_ptobs[scm_numptob].fflush = ptob->fflush;
116 scm_ptobs[scm_numptob].fgetc = ptob->fgetc;
3cb988bd 117 scm_ptobs[scm_numptob].fgets = ptob->fgets;
0f2d19dd
JB
118 scm_ptobs[scm_numptob].fclose = ptob->fclose;
119 scm_numptob++;
120 }
121 SCM_ALLOW_INTS;
122 if (!tmp)
123 ptoberr:scm_wta (SCM_MAKINUM ((long) scm_numptob), (char *) SCM_NALLOC, "newptob");
124 return scm_tc7_port + (scm_numptob - 1) * 256;
125}
126
127\f
128/* internal SCM call */
1cc91f1b 129
0f2d19dd
JB
130void
131scm_fflush (port)
132 SCM port;
0f2d19dd
JB
133{
134 scm_sizet i = SCM_PTOBNUM (port);
135 (scm_ptobs[i].fflush) (SCM_STREAM (port));
136}
137
138\f
139
44493941 140SCM_PROC(s_char_ready_p, "char-ready?", 0, 1, 0, scm_char_ready_p);
1cc91f1b 141
0f2d19dd
JB
142SCM
143scm_char_ready_p (port)
144 SCM port;
0f2d19dd
JB
145{
146 if (SCM_UNBNDP (port))
147 port = scm_cur_inp;
148 else
149 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_char_ready_p);
150 if (SCM_CRDYP (port) || !SCM_FPORTP (port))
151 return SCM_BOOL_T;
5d09ff4e
MD
152 return (scm_input_waiting_p ((FILE *) SCM_STREAM (port), s_char_ready_p)
153 ? SCM_BOOL_T
154 : SCM_BOOL_F);
0f2d19dd 155}
0f2d19dd
JB
156
157
158\f
159
160
161/* {Standard Ports}
162 */
163SCM_PROC(s_current_input_port, "current-input-port", 0, 0, 0, scm_current_input_port);
1cc91f1b 164
0f2d19dd
JB
165SCM
166scm_current_input_port ()
0f2d19dd
JB
167{
168 return scm_cur_inp;
169}
170
171SCM_PROC(s_current_output_port, "current-output-port", 0, 0, 0, scm_current_output_port);
1cc91f1b 172
0f2d19dd
JB
173SCM
174scm_current_output_port ()
0f2d19dd
JB
175{
176 return scm_cur_outp;
177}
178
179SCM_PROC(s_current_error_port, "current-error-port", 0, 0, 0, scm_current_error_port);
1cc91f1b 180
0f2d19dd
JB
181SCM
182scm_current_error_port ()
0f2d19dd
JB
183{
184 return scm_cur_errp;
185}
186
187SCM_PROC(s_set_current_input_port, "set-current-input-port", 1, 0, 0, scm_set_current_input_port);
1cc91f1b 188
0f2d19dd
JB
189SCM
190scm_set_current_input_port (port)
191 SCM port;
0f2d19dd
JB
192{
193 SCM oinp = scm_cur_inp;
194 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_set_current_input_port);
195 scm_cur_inp = port;
196 return oinp;
197}
198
199
200SCM_PROC(s_set_current_output_port, "set-current-output-port", 1, 0, 0, scm_set_current_output_port);
1cc91f1b 201
0f2d19dd
JB
202SCM
203scm_set_current_output_port (port)
204 SCM port;
0f2d19dd
JB
205{
206 SCM ooutp = scm_cur_outp;
207 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_set_current_output_port);
208 scm_cur_outp = port;
209 return ooutp;
210}
211
212
213SCM_PROC(s_set_current_error_port, "set-current-error-port", 1, 0, 0, scm_set_current_error_port);
1cc91f1b 214
0f2d19dd
JB
215SCM
216scm_set_current_error_port (port)
217 SCM port;
0f2d19dd
JB
218{
219 SCM oerrp = scm_cur_errp;
220 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_set_current_error_port);
221 scm_cur_errp = port;
222 return oerrp;
223}
224
225\f
226
227/* {Ports - in general}
228 *
229 */
230
231/* Array of open ports, required for reliable MOVE->FDES etc. */
232struct scm_port_table **scm_port_table;
233
234int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
235int scm_port_table_room = 20; /* Size of the array. */
236
237/* Add a port to the table. Call with SCM_DEFER_INTS active. */
1cc91f1b 238
0f2d19dd
JB
239struct scm_port_table *
240scm_add_to_port_table (port)
241 SCM port;
0f2d19dd
JB
242{
243 if (scm_port_table_size == scm_port_table_room)
244 {
245 scm_port_table = ((struct scm_port_table **)
246 realloc ((char *) scm_port_table,
247 (long) (sizeof (struct scm_port_table)
248 * scm_port_table_room * 2)));
249 /* !!! error checking */
250 scm_port_table_room *= 2;
251 }
252 scm_port_table[scm_port_table_size] = ((struct scm_port_table *)
253 scm_must_malloc (sizeof (struct scm_port_table),
254 "system port table"));
255 scm_port_table[scm_port_table_size]->port = port;
256 scm_port_table[scm_port_table_size]->revealed = 0;
257 scm_port_table[scm_port_table_size]->stream = 0;
ebf7394e 258 scm_port_table[scm_port_table_size]->file_name = SCM_BOOL_F;
0f2d19dd
JB
259 scm_port_table[scm_port_table_size]->line_number = 1;
260 scm_port_table[scm_port_table_size]->column_number = 0;
0f2d19dd
JB
261 return scm_port_table[scm_port_table_size++];
262}
263
264/* Remove a port from the table. Call with SCM_DEFER_INTS active. */
1cc91f1b 265
0f2d19dd
JB
266void
267scm_remove_from_port_table (port)
268 SCM port;
0f2d19dd
JB
269{
270 int i = 0;
271 while (scm_port_table[i]->port != port)
272 {
273 i++;
274 /* Error if not found: too violent? May occur in GC. */
275 if (i >= scm_port_table_size)
276 scm_wta (port, "Port not in table", "scm_remove_from_port_table");
277 }
278 scm_must_free ((char *)scm_port_table[i]);
279 scm_mallocated -= sizeof (*scm_port_table[i]);
280 scm_port_table[i] = scm_port_table[scm_port_table_size - 1];
281 SCM_SETPTAB_ENTRY (port, 0);
282 scm_port_table_size--;
283}
284
fea6b4ea 285#ifdef GUILE_DEBUG
0f2d19dd
JB
286/* Undocumented functions for debugging. */
287/* Return the number of ports in the table. */
1cc91f1b 288
1146b6cd 289SCM_PROC(s_pt_size, "pt-size", 0, 0, 0, scm_pt_size);
0f2d19dd
JB
290SCM
291scm_pt_size ()
0f2d19dd
JB
292{
293 return SCM_MAKINUM (scm_port_table_size);
294}
295
296/* Return the ith member of the port table. */
1146b6cd 297SCM_PROC(s_pt_member, "pt-member", 1, 0, 0, scm_pt_member);
0f2d19dd
JB
298SCM
299scm_pt_member (member)
300 SCM member;
0f2d19dd
JB
301{
302 int i;
303 SCM_ASSERT (SCM_INUMP (member), member, SCM_ARG1, s_pt_member);
304 i = SCM_INUM (member);
305 if (i < 0 || i >= scm_port_table_size)
306 return SCM_BOOL_F;
307 else
308 return scm_port_table[i]->port;
309}
310#endif
311
312
8b13c6b3
GH
313/* Find a port in the table and return its revealed count.
314 Also used by the garbage collector.
0f2d19dd 315 */
1cc91f1b 316
0f2d19dd
JB
317int
318scm_revealed_count (port)
319 SCM port;
0f2d19dd
JB
320{
321 return SCM_REVEALED(port);
322}
323
324
325
326/* Return the revealed count for a port. */
327
328SCM_PROC(s_port_revealed, "port-revealed", 1, 0, 0, scm_port_revealed);
1cc91f1b 329
0f2d19dd
JB
330SCM
331scm_port_revealed (port)
332 SCM port;
0f2d19dd 333{
0f2d19dd 334 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port), port, SCM_ARG1, s_port_revealed);
8b13c6b3 335 return SCM_MAKINUM (scm_revealed_count (port));
0f2d19dd
JB
336}
337
338/* Set the revealed count for a port. */
339SCM_PROC(s_set_port_revealed_x, "set-port-revealed!", 2, 0, 0, scm_set_port_revealed_x);
1cc91f1b 340
0f2d19dd
JB
341SCM
342scm_set_port_revealed_x (port, rcount)
343 SCM port;
344 SCM rcount;
0f2d19dd
JB
345{
346 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port), port, SCM_ARG1, s_set_port_revealed_x);
347 SCM_ASSERT (SCM_INUMP (rcount), rcount, SCM_ARG2, s_set_port_revealed_x);
348 SCM_DEFER_INTS;
349 SCM_REVEALED (port) = SCM_INUM (rcount);
350 SCM_ALLOW_INTS;
8b13c6b3 351 return SCM_UNSPECIFIED;
0f2d19dd
JB
352}
353
eadd48de
GH
354/* Return the flags that characterize a port based on the mode
355 * string used to open a file for that port.
356 *
357 * See PORT FLAGS in scm.h
358 */
359
360long
361scm_mode_bits (modes)
362 char *modes;
363{
364 return (SCM_OPN
365 | (strchr (modes, 'r') || strchr (modes, '+') ? SCM_RDNG : 0)
366 | ( strchr (modes, 'w')
367 || strchr (modes, 'a')
368 || strchr (modes, '+') ? SCM_WRTNG : 0)
369 | (strchr (modes, '0') ? SCM_BUF0 : 0));
370}
371
372
373/* Return the mode flags from an open port.
374 * Some modes such as "append" are only used when opening
375 * a file and are not returned here. */
376
377SCM_PROC(s_port_mode, "port-mode", 1, 0, 0, scm_port_mode);
378
379SCM
380scm_port_mode (port)
381 SCM port;
382{
383 char modes[3];
384 modes[0] = '\0';
385 SCM_ASSERT (SCM_NIMP (port) && SCM_OPPORTP (port), port, SCM_ARG1, s_port_mode);
386 if (SCM_CAR (port) & SCM_RDNG) {
387 if (SCM_CAR (port) & SCM_WRTNG)
388 strcpy (modes, "r+");
389 else
390 strcpy (modes, "r");
391 }
392 else if (SCM_CAR (port) & SCM_WRTNG)
393 strcpy (modes, "w");
394 if (SCM_CAR (port) & SCM_BUF0)
395 strcat (modes, "0");
396 return scm_makfromstr (modes, strlen (modes), 0);
397}
398
399
0f2d19dd
JB
400/* scm_close_port
401 * Call the close operation on a port object.
eadd48de 402 * see also scm_close.
0f2d19dd
JB
403 */
404SCM_PROC(s_close_port, "close-port", 1, 0, 0, scm_close_port);
1cc91f1b 405
0f2d19dd
JB
406SCM
407scm_close_port (port)
408 SCM port;
0f2d19dd
JB
409{
410 scm_sizet i;
eadd48de
GH
411 int rv;
412
0f2d19dd
JB
413 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port), port, SCM_ARG1, s_close_port);
414 if (SCM_CLOSEDP (port))
eadd48de 415 return SCM_BOOL_F;
0f2d19dd
JB
416 i = SCM_PTOBNUM (port);
417 SCM_DEFER_INTS;
418 if (scm_ptobs[i].fclose)
eadd48de
GH
419 {
420 SCM_SYSCALL (rv = (scm_ptobs[i].fclose) (SCM_STREAM (port)));
421 /* ports with a closed file descriptor can be reclosed without error. */
422 if (rv < 0 && errno != EBADF)
423 scm_syserror (s_close_port);
424 }
425 else
426 rv = 0;
0f2d19dd 427 scm_remove_from_port_table (port);
898a256f 428 SCM_SETAND_CAR (port, ~SCM_OPN);
0f2d19dd 429 SCM_ALLOW_INTS;
eadd48de 430 return (rv < 0) ? SCM_BOOL_F : SCM_BOOL_T;
0f2d19dd
JB
431}
432
433SCM_PROC(s_close_all_ports_except, "close-all-ports-except", 0, 0, 1, scm_close_all_ports_except);
1cc91f1b 434
0f2d19dd
JB
435SCM
436scm_close_all_ports_except (ports)
437 SCM ports;
0f2d19dd
JB
438{
439 int i = 0;
440 SCM_ASSERT (SCM_NIMP (ports) && SCM_CONSP (ports), ports, SCM_ARG1, s_close_all_ports_except);
441 SCM_DEFER_INTS;
442 while (i < scm_port_table_size)
443 {
444 SCM thisport = scm_port_table[i]->port;
445 int found = 0;
446 SCM ports_ptr = ports;
447
448 while (SCM_NNULLP (ports_ptr))
449 {
450 SCM port = SCM_CAR (ports_ptr);
451 if (i == 0)
452 SCM_ASSERT (SCM_NIMP (port) && SCM_OPPORTP (port), port, SCM_ARG1, s_close_all_ports_except);
453 if (port == thisport)
454 found = 1;
455 ports_ptr = SCM_CDR (ports_ptr);
456 }
457 if (found)
458 i++;
459 else
460 /* i is not to be incremented here. */
461 scm_close_port (thisport);
462 }
463 SCM_ALLOW_INTS;
464 return SCM_UNSPECIFIED;
465}
466
467SCM_PROC(s_input_port_p, "input-port?", 1, 0, 0, scm_input_port_p);
1cc91f1b 468
0f2d19dd
JB
469SCM
470scm_input_port_p (x)
471 SCM x;
0f2d19dd
JB
472{
473 if (SCM_IMP (x))
474 return SCM_BOOL_F;
475 return SCM_INPORTP (x) ? SCM_BOOL_T : SCM_BOOL_F;
476}
477
478SCM_PROC(s_output_port_p, "output-port?", 1, 0, 0, scm_output_port_p);
1cc91f1b 479
0f2d19dd
JB
480SCM
481scm_output_port_p (x)
482 SCM x;
0f2d19dd
JB
483{
484 if (SCM_IMP (x))
485 return SCM_BOOL_F;
486 return SCM_OUTPORTP (x) ? SCM_BOOL_T : SCM_BOOL_F;
487}
488
489
490SCM_PROC(s_eof_object_p, "eof-object?", 1, 0, 0, scm_eof_object_p);
1cc91f1b 491
0f2d19dd
JB
492SCM
493scm_eof_object_p (x)
494 SCM x;
0f2d19dd 495{
0c32d76c 496 return SCM_EOF_OBJECT_P (x) ? SCM_BOOL_T : SCM_BOOL_F;
0f2d19dd
JB
497}
498
499SCM_PROC(s_force_output, "force-output", 0, 1, 0, scm_force_output);
1cc91f1b 500
0f2d19dd
JB
501SCM
502scm_force_output (port)
503 SCM port;
0f2d19dd
JB
504{
505 if (SCM_UNBNDP (port))
506 port = scm_cur_outp;
507 else
508 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_force_output);
509 {
510 scm_sizet i = SCM_PTOBNUM (port);
511 SCM_SYSCALL ((scm_ptobs[i].fflush) (SCM_STREAM (port)));
512 return SCM_UNSPECIFIED;
513 }
514}
515
9c29ac66 516SCM_PROC (s_flush_all_ports, "flush-all-ports", 0, 0, 0, scm_flush_all_ports);
89ea5b7c
GH
517SCM
518scm_flush_all_ports (void)
519{
520 int i;
521
522 for (i = 0; i < scm_port_table_size; i++)
523 {
524 SCM port = scm_port_table[i]->port;
525 if (SCM_OPOUTPORTP (port))
526 {
527 scm_sizet ptob = SCM_PTOBNUM (port);
528 (scm_ptobs[ptob].fflush) (SCM_STREAM (port));
529 }
530 }
531 return SCM_UNSPECIFIED;
532}
0f2d19dd
JB
533
534SCM_PROC(s_read_char, "read-char", 0, 1, 0, scm_read_char);
1cc91f1b 535
0f2d19dd
JB
536SCM
537scm_read_char (port)
538 SCM port;
0f2d19dd
JB
539{
540 int c;
541 if (SCM_UNBNDP (port))
334341aa 542 port = scm_cur_inp;
0f2d19dd
JB
543 else
544 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_read_char);
b7f3516f 545 c = scm_getc (port);
0f2d19dd
JB
546 if (EOF == c)
547 return SCM_EOF_VAL;
548 return SCM_MAKICHR (c);
549}
550
551
552SCM_PROC(s_peek_char, "peek-char", 0, 1, 0, scm_peek_char);
1cc91f1b 553
0f2d19dd
JB
554SCM
555scm_peek_char (port)
556 SCM port;
0f2d19dd
JB
557{
558 int c;
559 if (SCM_UNBNDP (port))
560 port = scm_cur_inp;
561 else
562 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1, s_peek_char);
b7f3516f 563 c = scm_getc (port);
0f2d19dd
JB
564 if (EOF == c)
565 return SCM_EOF_VAL;
b7f3516f 566 scm_ungetc (c, port);
0f2d19dd
JB
567 return SCM_MAKICHR (c);
568}
569
3cb988bd
TP
570/*
571 * A generic fgets method. We supply this method so that ports which
572 * can't use fgets(3) (like string ports or soft ports) can still use
573 * line-based i/o. The generic method calls the port's own fgetc method
574 * for input. It should be possible to write a more efficient
575 * method for any given port representation -- this is supplied just
576 * to ensure that you don't have to.
577 */
578
579char * scm_generic_fgets SCM_P ((SCM port));
580
581char *
582scm_generic_fgets (port)
583 SCM port;
584{
585 SCM f = SCM_STREAM (port);
586 scm_sizet p = SCM_PTOBNUM (port);
587
588 char *buf = NULL;
589 int i = 0; /* index into current buffer position */
590 int limit = 80; /* current size of buffer */
591 int c;
592
593 if (feof ((FILE *)f))
594 return NULL;
595
596 buf = (char *) scm_must_malloc (limit * sizeof(char), "generic_fgets");
597
598 while (1) {
599 if (i >= limit-1)
600 {
601 buf = (char *) scm_must_realloc (buf,
602 sizeof(char) * limit,
603 sizeof(char) * limit * 2,
604 "generic_fgets");
605 limit *= 2;
606 }
607
608 c = (scm_ptobs[p].fgetc) (f);
609 if (c != EOF)
610 buf[i++] = c;
611
612 if (c == EOF || c == '\n')
613 {
614 if (i)
615 {
616 buf[i] = '\0';
617 return buf;
618 }
619 scm_must_free (buf);
620 return NULL;
621 }
622 }
623}
624
0f2d19dd 625SCM_PROC (s_unread_char, "unread-char", 2, 0, 0, scm_unread_char);
1cc91f1b 626
0f2d19dd
JB
627SCM
628scm_unread_char (cobj, port)
629 SCM cobj;
630 SCM port;
0f2d19dd
JB
631{
632 int c;
633
634 SCM_ASSERT (SCM_ICHRP (cobj), cobj, SCM_ARG1, s_unread_char);
635
636 if (SCM_UNBNDP (port))
637 port = scm_cur_inp;
638 else
639 SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG2, s_unread_char);
640
641
642 c = SCM_ICHR (cobj);
643
b7f3516f 644 scm_ungetc (c, port);
0f2d19dd
JB
645 return cobj;
646}
647
d14af9f2 648SCM_PROC (s_port_line, "port-line", 0, 1, 0, scm_port_line);
1cc91f1b 649
0f2d19dd 650SCM
d14af9f2 651scm_port_line (port)
0f2d19dd 652 SCM port;
0f2d19dd
JB
653{
654 SCM p;
655 p = ((port == SCM_UNDEFINED)
656 ? scm_cur_inp
657 : port);
658 if (!(SCM_NIMP (p) && SCM_PORTP (p)))
659 return SCM_BOOL_F;
660 else
661 return SCM_MAKINUM (SCM_LINUM (p));
662}
663
d043d8c2
MD
664SCM_PROC (s_set_port_line_x, "set-port-line!", 1, 1, 0, scm_set_port_line_x);
665
666SCM
667scm_set_port_line_x (port, line)
668 SCM port;
669 SCM line;
670{
671 if (line == SCM_UNDEFINED)
672 {
673 line = port;
674 port = scm_cur_inp;
675 }
676 else
677 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
678 port,
679 SCM_ARG1,
680 s_set_port_line_x);
681 return SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
682}
683
d14af9f2 684SCM_PROC (s_port_column, "port-column", 0, 1, 0, scm_port_column);
1cc91f1b 685
0f2d19dd 686SCM
d14af9f2 687scm_port_column (port)
0f2d19dd 688 SCM port;
0f2d19dd
JB
689{
690 SCM p;
691 p = ((port == SCM_UNDEFINED)
692 ? scm_cur_inp
693 : port);
694 if (!(SCM_NIMP (p) && SCM_PORTP (p)))
695 return SCM_BOOL_F;
696 else
697 return SCM_MAKINUM (SCM_COL (p));
698}
699
d043d8c2
MD
700SCM_PROC (s_set_port_column_x, "set-port-column!", 1, 1, 0, scm_set_port_column_x);
701
702SCM
703scm_set_port_column_x (port, column)
704 SCM port;
705 SCM column;
706{
707 if (column == SCM_UNDEFINED)
708 {
709 column = port;
710 port = scm_cur_inp;
711 }
712 else
713 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
714 port,
715 SCM_ARG1,
716 s_set_port_column_x);
717 return SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
718}
719
d14af9f2 720SCM_PROC (s_port_filename, "port-filename", 0, 1, 0, scm_port_filename);
1cc91f1b 721
0f2d19dd 722SCM
d14af9f2 723scm_port_filename (port)
0f2d19dd 724 SCM port;
0f2d19dd
JB
725{
726 SCM p;
727 p = ((port == SCM_UNDEFINED)
728 ? scm_cur_inp
729 : port);
730 if (!(SCM_NIMP (p) && SCM_PORTP (p)))
731 return SCM_BOOL_F;
732 else
733 return SCM_PTAB_ENTRY (p)->file_name;
734}
735
d14af9f2 736SCM_PROC (s_set_port_filename_x, "set-port-filename!", 1, 1, 0, scm_set_port_filename_x);
1cc91f1b 737
d14af9f2
MD
738SCM
739scm_set_port_filename_x (port, filename)
740 SCM port;
741 SCM filename;
d14af9f2
MD
742{
743 if (filename == SCM_UNDEFINED)
744 {
745 filename = port;
746 port = scm_cur_inp;
747 }
748 else
749 SCM_ASSERT (SCM_NIMP (port) && SCM_PORTP (port) && SCM_OPENP (port),
750 port,
751 SCM_ARG1,
752 s_set_port_filename_x);
753 return SCM_PTAB_ENTRY (port)->file_name = filename;
754}
755
0f2d19dd
JB
756#ifndef ttyname
757extern char * ttyname();
758#endif
759
1cc91f1b 760
0f2d19dd
JB
761void
762scm_prinport (exp, port, type)
763 SCM exp;
764 SCM port;
765 char *type;
0f2d19dd 766{
b7f3516f 767 scm_puts ("#<", port);
0f2d19dd 768 if (SCM_CLOSEDP (exp))
b7f3516f 769 scm_puts ("closed: ", port);
0f2d19dd
JB
770 else
771 {
772 if (SCM_RDNG & SCM_CAR (exp))
b7f3516f 773 scm_puts ("input: ", port);
0f2d19dd 774 if (SCM_WRTNG & SCM_CAR (exp))
b7f3516f 775 scm_puts ("output: ", port);
0f2d19dd 776 }
b7f3516f
TT
777 scm_puts (type, port);
778 scm_putc (' ', port);
0f2d19dd
JB
779#ifndef MSDOS
780#ifndef __EMX__
781#ifndef _DCC
782#ifndef AMIGA
783#ifndef THINK_C
784 if (SCM_OPENP (exp) && scm_tc16_fport == SCM_TYP16 (exp) && isatty (fileno ((FILE *)SCM_STREAM (exp))))
b7f3516f 785 scm_puts (ttyname (fileno ((FILE *)SCM_STREAM (exp))), port);
0f2d19dd
JB
786 else
787#endif
788#endif
789#endif
790#endif
791#endif
792 if (SCM_OPFPORTP (exp))
793 scm_intprint ((long) fileno ((FILE *)SCM_STREAM (exp)), 10, port);
794 else
795 scm_intprint (SCM_CDR (exp), 16, port);
b7f3516f 796 scm_putc ('>', port);
0f2d19dd
JB
797}
798
1cc91f1b 799
0f2d19dd
JB
800void
801scm_ports_prehistory ()
0f2d19dd
JB
802{
803 scm_numptob = 0;
804 scm_ptobs = (scm_ptobfuns *) malloc (sizeof (scm_ptobfuns));
805
806 /* WARNING: These scm_newptob calls must be done in this order.
807 * They must agree with the port declarations in tags.h.
808 */
809 /* scm_tc16_fport = */ scm_newptob (&scm_fptob);
810 /* scm_tc16_pipe = */ scm_newptob (&scm_pipob);
811 /* scm_tc16_strport = */ scm_newptob (&scm_stptob);
812 /* scm_tc16_sfport = */ scm_newptob (&scm_sfptob);
813}
814\f
815
816\f
817/* {Void Ports}
818 */
819
820int scm_tc16_void_port = 0;
821
822static int
38cb0e9c 823print_void_port (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
824{
825 scm_prinport (exp, port, "void");
826 return 1;
827}
828
829static int
38cb0e9c 830putc_void_port (int c, SCM strm)
0f2d19dd
JB
831{
832 return 0; /* vestigial return value */
833}
834
835static int
38cb0e9c 836puts_void_port (char *s, SCM strm)
0f2d19dd
JB
837{
838 return 0; /* vestigial return value */
839}
840
841static scm_sizet
38cb0e9c 842write_void_port (char *ptr, scm_sizet size, scm_sizet nitems, SCM strm)
0f2d19dd
JB
843{
844 int len;
845 len = size * nitems;
846 return len;
847}
848
1cc91f1b 849
0f2d19dd 850static int
38cb0e9c 851flush_void_port (SCM strm)
0f2d19dd
JB
852{
853 return 0;
854}
855
1cc91f1b 856
0f2d19dd 857static int
38cb0e9c 858getc_void_port (SCM strm)
0f2d19dd
JB
859{
860 return EOF;
861}
862
3cb988bd
TP
863static char *
864fgets_void_port (SCM strm)
865{
866 return NULL;
867}
1cc91f1b 868
0f2d19dd 869static int
38cb0e9c 870close_void_port (SCM strm)
0f2d19dd
JB
871{
872 return 0; /* this is ignored by scm_close_port. */
873}
874
875
1cc91f1b 876
0f2d19dd 877static int
38cb0e9c 878noop0 (SCM stream)
0f2d19dd
JB
879{
880 return 0;
881}
882
883
884static struct scm_ptobfuns void_port_ptob =
885{
886 scm_mark0,
887 noop0,
888 print_void_port,
889 0, /* equal? */
890 putc_void_port,
891 puts_void_port,
892 write_void_port,
893 flush_void_port,
894 getc_void_port,
3cb988bd 895 fgets_void_port,
0f2d19dd
JB
896 close_void_port,
897};
898
899\f
900
1cc91f1b 901
0f2d19dd
JB
902SCM
903scm_void_port (mode_str)
904 char * mode_str;
0f2d19dd
JB
905{
906 int mode_bits;
907 SCM answer;
908 struct scm_port_table * pt;
909
910 SCM_NEWCELL (answer);
911 SCM_DEFER_INTS;
912 mode_bits = scm_mode_bits (mode_str);
913 pt = scm_add_to_port_table (answer);
898a256f 914 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
0f2d19dd
JB
915 SCM_SETPTAB_ENTRY (answer, pt);
916 SCM_SETSTREAM (answer, SCM_BOOL_F);
917 SCM_ALLOW_INTS;
918 return answer;
919}
920
921
922SCM_PROC (s_sys_make_void_port, "%make-void-port", 1, 0, 0, scm_sys_make_void_port);
1cc91f1b 923
0f2d19dd
JB
924SCM
925scm_sys_make_void_port (mode)
926 SCM mode;
0f2d19dd 927{
89958ad0 928 SCM_ASSERT (SCM_NIMP (mode) && SCM_ROSTRINGP (mode), mode,
0f2d19dd
JB
929 SCM_ARG1, s_sys_make_void_port);
930
89958ad0 931 SCM_COERCE_SUBSTR (mode);
0f2d19dd
JB
932 return scm_void_port (SCM_ROCHARS (mode));
933}
934
935
936
937\f
938
1cc91f1b 939
0f2d19dd
JB
940void
941scm_init_ports ()
0f2d19dd
JB
942{
943 scm_tc16_void_port = scm_newptob (&void_port_ptob);
944#include "ports.x"
945}
946