* alist.c, chars.c, debug.c, dynl.c, dynwind.c, error.c, eval.c,
[bpt/guile.git] / libguile / ports.c
1 /* Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
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, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
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.
40 * If you do not wish that, delete this exception notice. */
41
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45 \f
46 /* Headers. */
47
48 #include <stdio.h>
49 #include "_scm.h"
50 #include "objects.h"
51 #include "smob.h"
52 #include "chars.h"
53
54 #include "keywords.h"
55
56 #include "scm_validate.h"
57 #include "ports.h"
58
59 #ifdef HAVE_MALLOC_H
60 #include <malloc.h>
61 #endif
62
63 #ifdef HAVE_UNISTD_H
64 #include <unistd.h>
65 #endif
66
67 #ifdef HAVE_SYS_IOCTL_H
68 #include <sys/ioctl.h>
69 #endif
70
71 \f
72 /* The port kind table --- a dynamically resized array of port types. */
73
74
75 /* scm_ptobs scm_numptob
76 * implement a dynamicly resized array of ptob records.
77 * Indexes into this table are used when generating type
78 * tags for smobjects (if you know a tag you can get an index and conversely).
79 */
80 scm_ptob_descriptor *scm_ptobs;
81 int scm_numptob;
82
83 /* GC marker for a port with stream of SCM type. */
84 SCM
85 scm_markstream (SCM ptr)
86 {
87 int openp;
88 openp = SCM_CAR (ptr) & SCM_OPN;
89 if (openp)
90 return SCM_STREAM (ptr);
91 else
92 return SCM_BOOL_F;
93 }
94
95 /*
96 * We choose to use an interface similar to the smob interface with
97 * fill_input and write as standard fields, passed to the port
98 * type constructor, and optional fields set by setters.
99 */
100
101 static void flush_void_port (SCM port);
102 static void end_input_void_port (SCM port, int offset);
103 static void write_void_port (SCM port, const void *data, size_t size);
104
105 long
106 scm_make_port_type (char *name,
107 int (*fill_input) (SCM port),
108 void (*write) (SCM port, const void *data, size_t size))
109 {
110 char *tmp;
111 if (255 <= scm_numptob)
112 goto ptoberr;
113 SCM_DEFER_INTS;
114 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
115 (1 + scm_numptob)
116 * sizeof (scm_ptob_descriptor)));
117 if (tmp)
118 {
119 scm_ptobs = (scm_ptob_descriptor *) tmp;
120
121 scm_ptobs[scm_numptob].name = name;
122 scm_ptobs[scm_numptob].mark = 0;
123 scm_ptobs[scm_numptob].free = scm_free0;
124 scm_ptobs[scm_numptob].print = scm_port_print;
125 scm_ptobs[scm_numptob].equalp = 0;
126 scm_ptobs[scm_numptob].close = 0;
127
128 scm_ptobs[scm_numptob].write = write;
129 scm_ptobs[scm_numptob].flush = flush_void_port;
130
131 scm_ptobs[scm_numptob].end_input = end_input_void_port;
132 scm_ptobs[scm_numptob].fill_input = fill_input;
133 scm_ptobs[scm_numptob].input_waiting = 0;
134
135 scm_ptobs[scm_numptob].seek = 0;
136 scm_ptobs[scm_numptob].truncate = 0;
137
138 scm_numptob++;
139 }
140 SCM_ALLOW_INTS;
141 if (!tmp)
142 ptoberr:scm_wta (SCM_MAKINUM ((long) scm_numptob),
143 (char *) SCM_NALLOC, "scm_make_port_type");
144 /* Make a class object if Goops is present */
145 if (scm_port_class)
146 scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
147 return scm_tc7_port + (scm_numptob - 1) * 256;
148 }
149
150 void
151 scm_set_port_mark (long tc, SCM (*mark) (SCM))
152 {
153 scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
154 }
155
156 void
157 scm_set_port_free (long tc, scm_sizet (*free) (SCM))
158 {
159 scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
160 }
161
162 void
163 scm_set_port_print (long tc, int (*print) (SCM exp, SCM port,
164 scm_print_state *pstate))
165 {
166 scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
167 }
168
169 void
170 scm_set_port_equalp (long tc, SCM (*equalp) (SCM, SCM))
171 {
172 scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
173 }
174
175 void
176 scm_set_port_flush (long tc, void (*flush) (SCM port))
177 {
178 scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
179 }
180
181 void
182 scm_set_port_end_input (long tc, void (*end_input) (SCM port, int offset))
183 {
184 scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
185 }
186
187 void
188 scm_set_port_close (long tc, int (*close) (SCM))
189 {
190 scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
191 }
192
193 void
194 scm_set_port_seek (long tc, off_t (*seek) (SCM port,
195 off_t OFFSET,
196 int WHENCE))
197 {
198 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
199 }
200
201 void
202 scm_set_port_truncate (long tc, void (*truncate) (SCM port, off_t length))
203 {
204 scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
205 }
206
207 void
208 scm_set_port_input_waiting (long tc, int (*input_waiting) (SCM))
209 {
210 scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
211 }
212
213 \f
214
215 SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
216 (SCM port),
217 "")
218 #define FUNC_NAME s_scm_char_ready_p
219 {
220 scm_port *pt;
221
222 if (SCM_UNBNDP (port))
223 port = scm_cur_inp;
224 else
225 SCM_VALIDATE_OPINPORT (1,port);
226
227 pt = SCM_PTAB_ENTRY (port);
228
229 /* if the current read buffer is filled, or the
230 last pushed-back char has been read and the saved buffer is
231 filled, result is true. */
232 if (pt->read_pos < pt->read_end
233 || (pt->read_buf == pt->putback_buf
234 && pt->saved_read_pos < pt->saved_read_end))
235 return SCM_BOOL_T;
236 else
237 {
238 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
239
240 if (ptob->input_waiting)
241 return SCM_BOOL(ptob->input_waiting (port));
242 else
243 return SCM_BOOL_T;
244 }
245 }
246 #undef FUNC_NAME
247
248 /* Clear a port's read buffers, returning the contents. */
249 SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
250 (SCM port),
251 "Drains @var{PORT}'s read buffers (including any pushed-back characters)\n"
252 "and returns the contents as a single string.")
253 #define FUNC_NAME s_scm_drain_input
254 {
255 SCM result;
256 scm_port *pt = SCM_PTAB_ENTRY (port);
257 int count;
258 char *dst;
259
260 SCM_VALIDATE_OPINPORT (1,port);
261
262 count = pt->read_end - pt->read_pos;
263 if (pt->read_buf == pt->putback_buf)
264 count += pt->saved_read_end - pt->saved_read_pos;
265
266 result = scm_makstr (count, 0);
267 dst = SCM_CHARS (result);
268
269 while (pt->read_pos < pt->read_end)
270 *dst++ = *(pt->read_pos++);
271
272 if (pt->read_buf == pt->putback_buf)
273 {
274 while (pt->saved_read_pos < pt->saved_read_end)
275 *dst++ = *(pt->saved_read_pos++);
276 }
277
278 return result;
279 }
280 #undef FUNC_NAME
281
282 \f
283 /* Standard ports --- current input, output, error, and more(!). */
284
285 SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
286 (),
287 "")
288 #define FUNC_NAME s_scm_current_input_port
289 {
290 return scm_cur_inp;
291 }
292 #undef FUNC_NAME
293
294 SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
295 (),
296 "")
297 #define FUNC_NAME s_scm_current_output_port
298 {
299 return scm_cur_outp;
300 }
301 #undef FUNC_NAME
302
303 SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
304 (),
305 "Return the port to which errors and warnings should be sent (the\n"
306 "@dfn{standard error} in Unix and C terminology).")
307 #define FUNC_NAME s_scm_current_error_port
308 {
309 return scm_cur_errp;
310 }
311 #undef FUNC_NAME
312
313 SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
314 (),
315 "")
316 #define FUNC_NAME s_scm_current_load_port
317 {
318 return scm_cur_loadp;
319 }
320 #undef FUNC_NAME
321
322 SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
323 (SCM port),
324 "@deffnx primitive set-current-output-port port\n"
325 "@deffnx primitive set-current-error-port port\n"
326 "Change the ports returned by @code{current-input-port},\n"
327 "@code{current-output-port} and @code{current-error-port}, respectively,\n"
328 "so that they use the supplied @var{port} for input or output.")
329 #define FUNC_NAME s_scm_set_current_input_port
330 {
331 SCM oinp = scm_cur_inp;
332 SCM_VALIDATE_OPINPORT (1,port);
333 scm_cur_inp = port;
334 return oinp;
335 }
336 #undef FUNC_NAME
337
338
339 SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
340 (SCM port),
341 "")
342 #define FUNC_NAME s_scm_set_current_output_port
343 {
344 SCM ooutp = scm_cur_outp;
345 port = SCM_COERCE_OUTPORT (port);
346 SCM_VALIDATE_OPOUTPORT (1,port);
347 scm_cur_outp = port;
348 return ooutp;
349 }
350 #undef FUNC_NAME
351
352
353 SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
354 (SCM port),
355 "")
356 #define FUNC_NAME s_scm_set_current_error_port
357 {
358 SCM oerrp = scm_cur_errp;
359 port = SCM_COERCE_OUTPORT (port);
360 SCM_VALIDATE_OPOUTPORT (1,port);
361 scm_cur_errp = port;
362 return oerrp;
363 }
364 #undef FUNC_NAME
365
366 \f
367 /* The port table --- an array of pointers to ports. */
368
369 scm_port **scm_port_table;
370
371 int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
372 int scm_port_table_room = 20; /* Size of the array. */
373
374 /* Add a port to the table. */
375
376 scm_port *
377 scm_add_to_port_table (SCM port)
378 {
379 scm_port *entry;
380
381 if (scm_port_table_size == scm_port_table_room)
382 {
383 void *newt = realloc ((char *) scm_port_table,
384 (scm_sizet) (sizeof (scm_port *)
385 * scm_port_table_room * 2));
386 if (newt == NULL)
387 scm_memory_error ("scm_add_to_port_table");
388 scm_port_table = (scm_port **) newt;
389 scm_port_table_room *= 2;
390 }
391 entry = (scm_port *) malloc (sizeof (scm_port));
392 if (entry == NULL)
393 scm_memory_error ("scm_add_to_port_table");
394
395 entry->port = port;
396 entry->entry = scm_port_table_size;
397 entry->revealed = 0;
398 entry->stream = 0;
399 entry->file_name = SCM_BOOL_F;
400 entry->line_number = 0;
401 entry->column_number = 0;
402 entry->putback_buf = 0;
403 entry->putback_buf_size = 0;
404 entry->rw_active = SCM_PORT_NEITHER;
405 entry->rw_random = 0;
406
407 scm_port_table[scm_port_table_size] = entry;
408 scm_port_table_size++;
409
410 return entry;
411 }
412
413 /* Remove a port from the table and destroy it. */
414
415 void
416 scm_remove_from_port_table (SCM port)
417 {
418 scm_port *p = SCM_PTAB_ENTRY (port);
419 int i = p->entry;
420
421 if (i >= scm_port_table_size)
422 scm_wta (port, "Port not in table", "scm_remove_from_port_table");
423 if (p->putback_buf)
424 free (p->putback_buf);
425 free (p);
426 /* Since we have just freed slot i we can shrink the table by moving
427 the last entry to that slot... */
428 if (i < scm_port_table_size - 1)
429 {
430 scm_port_table[i] = scm_port_table[scm_port_table_size - 1];
431 scm_port_table[i]->entry = i;
432 }
433 SCM_SETPTAB_ENTRY (port, 0);
434 scm_port_table_size--;
435 }
436
437 #ifdef GUILE_DEBUG
438 /* Undocumented functions for debugging. */
439 /* Return the number of ports in the table. */
440
441 SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
442 (),
443 "")
444 #define FUNC_NAME s_scm_pt_size
445 {
446 return SCM_MAKINUM (scm_port_table_size);
447 }
448 #undef FUNC_NAME
449
450 /* Return the ith member of the port table. */
451 SCM_DEFINE (scm_pt_member, "pt-member", 1, 0, 0,
452 (SCM member),
453 "")
454 #define FUNC_NAME s_scm_pt_member
455 {
456 int i;
457 SCM_VALIDATE_INUM_COPY (1,member,i);
458 if (i < 0 || i >= scm_port_table_size)
459 return SCM_BOOL_F;
460 else
461 return scm_port_table[i]->port;
462 }
463 #undef FUNC_NAME
464 #endif
465
466
467 \f
468 /* Revealed counts --- an oddity inherited from SCSH. */
469
470 /* Find a port in the table and return its revealed count.
471 Also used by the garbage collector.
472 */
473
474 int
475 scm_revealed_count (SCM port)
476 {
477 return SCM_REVEALED(port);
478 }
479
480
481
482 /* Return the revealed count for a port. */
483
484 SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
485 (SCM port),
486 "Returns the revealed count for @var{port}.")
487 #define FUNC_NAME s_scm_port_revealed
488 {
489 port = SCM_COERCE_OUTPORT (port);
490 SCM_VALIDATE_PORT (1,port);
491 return SCM_MAKINUM (scm_revealed_count (port));
492 }
493 #undef FUNC_NAME
494
495 /* Set the revealed count for a port. */
496 SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
497 (SCM port, SCM rcount),
498 "Sets the revealed count for a port to a given value. \n"
499 "The return value is unspecified.")
500 #define FUNC_NAME s_scm_set_port_revealed_x
501 {
502 port = SCM_COERCE_OUTPORT (port);
503 SCM_VALIDATE_PORT (1,port);
504 SCM_VALIDATE_INUM (2,rcount);
505 SCM_REVEALED (port) = SCM_INUM (rcount);
506 return SCM_UNSPECIFIED;
507 }
508 #undef FUNC_NAME
509
510
511 \f
512 /* Retrieving a port's mode. */
513
514 /* Return the flags that characterize a port based on the mode
515 * string used to open a file for that port.
516 *
517 * See PORT FLAGS in scm.h
518 */
519
520 long
521 scm_mode_bits (char *modes)
522 {
523 return (SCM_OPN
524 | (strchr (modes, 'r') || strchr (modes, '+') ? SCM_RDNG : 0)
525 | ( strchr (modes, 'w')
526 || strchr (modes, 'a')
527 || strchr (modes, '+') ? SCM_WRTNG : 0)
528 | (strchr (modes, '0') ? SCM_BUF0 : 0)
529 | (strchr (modes, 'l') ? SCM_BUFLINE : 0));
530 }
531
532
533 /* Return the mode flags from an open port.
534 * Some modes such as "append" are only used when opening
535 * a file and are not returned here. */
536
537 SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
538 (SCM port),
539 "Returns the port modes associated with the open port @var{port}. These\n"
540 "will not necessarily be identical to the modes used when the port was\n"
541 "opened, since modes such as \"append\" which are used only during\n"
542 "port creation are not retained.")
543 #define FUNC_NAME s_scm_port_mode
544 {
545 char modes[3];
546 modes[0] = '\0';
547
548 port = SCM_COERCE_OUTPORT (port);
549 SCM_VALIDATE_OPPORT (1,port);
550 if (SCM_CAR (port) & SCM_RDNG) {
551 if (SCM_CAR (port) & SCM_WRTNG)
552 strcpy (modes, "r+");
553 else
554 strcpy (modes, "r");
555 }
556 else if (SCM_CAR (port) & SCM_WRTNG)
557 strcpy (modes, "w");
558 if (SCM_CAR (port) & SCM_BUF0)
559 strcat (modes, "0");
560 return scm_makfromstr (modes, strlen (modes), 0);
561 }
562 #undef FUNC_NAME
563
564
565 \f
566 /* Closing ports. */
567
568 /* scm_close_port
569 * Call the close operation on a port object.
570 * see also scm_close.
571 */
572 SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
573 (SCM port),
574 "Close the specified port object. Returns @code{#t} if it successfully\n"
575 "closes a port or @code{#f} if it was already\n"
576 "closed. An exception may be raised if an error occurs, for example\n"
577 "when flushing buffered output.\n"
578 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
579 "which can close file descriptors.")
580 #define FUNC_NAME s_scm_close_port
581 {
582 scm_sizet i;
583 int rv;
584
585 port = SCM_COERCE_OUTPORT (port);
586
587 SCM_VALIDATE_PORT (1,port);
588 if (SCM_CLOSEDP (port))
589 return SCM_BOOL_F;
590 i = SCM_PTOBNUM (port);
591 if (scm_ptobs[i].close)
592 rv = (scm_ptobs[i].close) (port);
593 else
594 rv = 0;
595 scm_remove_from_port_table (port);
596 SCM_SETAND_CAR (port, ~SCM_OPN);
597 return SCM_NEGATE_BOOL(rv < 0);
598 }
599 #undef FUNC_NAME
600
601 SCM_DEFINE (scm_close_all_ports_except, "close-all-ports-except", 0, 0, 1,
602 (SCM ports),
603 "Close all open file ports used by the interpreter\n"
604 "except for those supplied as arguments. This procedure\n"
605 "is intended to be used before an exec call to close file descriptors\n"
606 "which are not needed in the new process.Close all open file ports used by the interpreter\n"
607 "except for those supplied as arguments. This procedure\n"
608 "is intended to be used before an exec call to close file descriptors\n"
609 "which are not needed in the new process.")
610 #define FUNC_NAME s_scm_close_all_ports_except
611 {
612 int i = 0;
613 SCM_VALIDATE_CONS (1,ports);
614 while (i < scm_port_table_size)
615 {
616 SCM thisport = scm_port_table[i]->port;
617 int found = 0;
618 SCM ports_ptr = ports;
619
620 while (SCM_NNULLP (ports_ptr))
621 {
622 SCM port = SCM_COERCE_OUTPORT (SCM_CAR (ports_ptr));
623 if (i == 0)
624 SCM_VALIDATE_OPPORT (SCM_ARG1,port);
625 if (port == thisport)
626 found = 1;
627 ports_ptr = SCM_CDR (ports_ptr);
628 }
629 if (found)
630 i++;
631 else
632 /* i is not to be incremented here. */
633 scm_close_port (thisport);
634 }
635 return SCM_UNSPECIFIED;
636 }
637 #undef FUNC_NAME
638
639
640 \f
641 /* Utter miscellany. Gosh, we should clean this up some time. */
642
643 SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
644 (SCM x),
645 "")
646 #define FUNC_NAME s_scm_input_port_p
647 {
648 if (SCM_IMP (x))
649 return SCM_BOOL_F;
650 return SCM_BOOL(SCM_INPORTP (x));
651 }
652 #undef FUNC_NAME
653
654 SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
655 (SCM x),
656 "")
657 #define FUNC_NAME s_scm_output_port_p
658 {
659 if (SCM_IMP (x))
660 return SCM_BOOL_F;
661 if (SCM_PORT_WITH_PS_P (x))
662 x = SCM_PORT_WITH_PS_PORT (x);
663 return SCM_BOOL(SCM_OUTPORTP (x));
664 }
665 #undef FUNC_NAME
666
667 SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
668 (SCM port),
669 "Returns @code{#t} if @var{port} is closed or @code{#f} if it is open.")
670 #define FUNC_NAME s_scm_port_closed_p
671 {
672 SCM_VALIDATE_PORT (1,port);
673 return SCM_NEGATE_BOOL(SCM_OPPORTP (port));
674 }
675 #undef FUNC_NAME
676
677 SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
678 (SCM x),
679 "")
680 #define FUNC_NAME s_scm_eof_object_p
681 {
682 return SCM_BOOL(SCM_EOF_OBJECT_P (x));
683 }
684 #undef FUNC_NAME
685
686 SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
687 (SCM port),
688 "Flush the specified output port, or the current output port if @var{port}\n"
689 "is omitted. The current output buffer contents are passed to the \n"
690 "underlying port implementation (e.g., in the case of fports, the\n"
691 "data will be written to the file and the output buffer will be cleared.)\n"
692 "It has no effect on an unbuffered port.\n\n"
693 "The return value is unspecified.")
694 #define FUNC_NAME s_scm_force_output
695 {
696 if (SCM_UNBNDP (port))
697 port = scm_cur_outp;
698 else
699 {
700 port = SCM_COERCE_OUTPORT (port);
701 SCM_VALIDATE_OPOUTPORT (1,port);
702 }
703 scm_flush (port);
704 return SCM_UNSPECIFIED;
705 }
706 #undef FUNC_NAME
707
708 SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
709 (),
710 "Equivalent to calling @code{force-output} on\n"
711 "all open output ports. The return value is unspecified.")
712 #define FUNC_NAME s_scm_flush_all_ports
713 {
714 int i;
715
716 for (i = 0; i < scm_port_table_size; i++)
717 {
718 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
719 scm_flush (scm_port_table[i]->port);
720 }
721 return SCM_UNSPECIFIED;
722 }
723 #undef FUNC_NAME
724
725 SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
726 (SCM port),
727 "")
728 #define FUNC_NAME s_scm_read_char
729 {
730 int c;
731 if (SCM_UNBNDP (port))
732 port = scm_cur_inp;
733 SCM_VALIDATE_OPINPORT (1,port);
734 c = scm_getc (port);
735 if (EOF == c)
736 return SCM_EOF_VAL;
737 return SCM_MAKICHR (c);
738 }
739 #undef FUNC_NAME
740
741 /* this should only be called when the read buffer is empty. it
742 tries to refill the read buffer. it returns the first char from
743 the port, which is either EOF or *(pt->read_pos). */
744 int
745 scm_fill_input (SCM port)
746 {
747 scm_port *pt = SCM_PTAB_ENTRY (port);
748
749 if (pt->read_buf == pt->putback_buf)
750 {
751 /* finished reading put-back chars. */
752 pt->read_buf = pt->saved_read_buf;
753 pt->read_pos = pt->saved_read_pos;
754 pt->read_end = pt->saved_read_end;
755 pt->read_buf_size = pt->saved_read_buf_size;
756 if (pt->read_pos < pt->read_end)
757 return *(pt->read_pos);
758 }
759 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
760 }
761
762 int
763 scm_getc (SCM port)
764 {
765 int c;
766 scm_port *pt = SCM_PTAB_ENTRY (port);
767
768 if (pt->rw_active == SCM_PORT_WRITE)
769 {
770 /* may be marginally faster than calling scm_flush. */
771 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
772 }
773
774 if (pt->rw_random)
775 pt->rw_active = SCM_PORT_READ;
776
777 if (pt->read_pos >= pt->read_end)
778 {
779 if (scm_fill_input (port) == EOF)
780 return EOF;
781 }
782
783 c = *(pt->read_pos++);
784
785 if (c == '\n')
786 {
787 SCM_INCLINE (port);
788 }
789 else if (c == '\t')
790 {
791 SCM_TABCOL (port);
792 }
793 else
794 {
795 SCM_INCCOL (port);
796 }
797
798 return c;
799 }
800
801 void
802 scm_putc (char c, SCM port)
803 {
804 scm_lfwrite (&c, 1, port);
805 }
806
807 void
808 scm_puts (const char *s, SCM port)
809 {
810 scm_lfwrite (s, strlen (s), port);
811 }
812
813 void
814 scm_lfwrite (const char *ptr, scm_sizet size, SCM port)
815 {
816 scm_port *pt = SCM_PTAB_ENTRY (port);
817 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
818
819 if (pt->rw_active == SCM_PORT_READ)
820 scm_end_input (port);
821
822 ptob->write (port, ptr, size);
823
824 if (pt->rw_random)
825 pt->rw_active = SCM_PORT_WRITE;
826 }
827
828
829 void
830 scm_flush (SCM port)
831 {
832 scm_sizet i = SCM_PTOBNUM (port);
833 (scm_ptobs[i].flush) (port);
834 }
835
836 void
837 scm_end_input (SCM port)
838 {
839 int offset;
840 scm_port *pt = SCM_PTAB_ENTRY (port);
841
842 if (pt->read_buf == pt->putback_buf)
843 {
844 offset = pt->read_end - pt->read_pos;
845 pt->read_buf = pt->saved_read_buf;
846 pt->read_pos = pt->saved_read_pos;
847 pt->read_end = pt->saved_read_end;
848 pt->read_buf_size = pt->saved_read_buf_size;
849 }
850 else
851 offset = 0;
852
853 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
854 }
855
856 \f
857
858
859 void
860 scm_ungetc (int c, SCM port)
861 {
862 scm_port *pt = SCM_PTAB_ENTRY (port);
863
864 if (pt->read_buf == pt->putback_buf)
865 /* already using the put-back buffer. */
866 {
867 /* enlarge putback_buf if necessary. */
868 if (pt->read_end == pt->read_buf + pt->read_buf_size
869 && pt->read_buf == pt->read_pos)
870 {
871 int new_size = pt->read_buf_size * 2;
872 unsigned char *tmp =
873 (unsigned char *) realloc (pt->putback_buf, new_size);
874
875 if (tmp == NULL)
876 scm_memory_error ("scm_ungetc");
877 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
878 pt->read_end = pt->read_buf + pt->read_buf_size;
879 pt->read_buf_size = pt->putback_buf_size = new_size;
880 }
881
882 /* shift any existing bytes to buffer + 1. */
883 if (pt->read_pos == pt->read_end)
884 pt->read_end = pt->read_buf + 1;
885 else if (pt->read_pos != pt->read_buf + 1)
886 {
887 int count = pt->read_end - pt->read_pos;
888
889 memmove (pt->read_buf + 1, pt->read_pos, count);
890 pt->read_end = pt->read_buf + 1 + count;
891 }
892
893 pt->read_pos = pt->read_buf;
894 }
895 else
896 /* switch to the put-back buffer. */
897 {
898 if (pt->putback_buf == NULL)
899 {
900 pt->putback_buf = (char *) malloc (SCM_INITIAL_PUTBACK_BUF_SIZE);
901 if (pt->putback_buf == NULL)
902 scm_memory_error ("scm_ungetc");
903 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
904 }
905
906 pt->saved_read_buf = pt->read_buf;
907 pt->saved_read_pos = pt->read_pos;
908 pt->saved_read_end = pt->read_end;
909 pt->saved_read_buf_size = pt->read_buf_size;
910
911 pt->read_pos = pt->read_buf = pt->putback_buf;
912 pt->read_end = pt->read_buf + 1;
913 pt->read_buf_size = pt->putback_buf_size;
914 }
915
916 *pt->read_buf = c;
917
918 if (pt->rw_random)
919 pt->rw_active = SCM_PORT_READ;
920
921 if (c == '\n')
922 {
923 /* What should col be in this case?
924 * We'll leave it at -1.
925 */
926 SCM_LINUM (port) -= 1;
927 }
928 else
929 SCM_COL(port) -= 1;
930 }
931
932
933 void
934 scm_ungets (const char *s, int n, SCM port)
935 {
936 /* This is simple minded and inefficient, but unreading strings is
937 * probably not a common operation, and remember that line and
938 * column numbers have to be handled...
939 *
940 * Please feel free to write an optimized version!
941 */
942 while (n--)
943 scm_ungetc (s[n], port);
944 }
945
946
947 SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
948 (SCM port),
949 "")
950 #define FUNC_NAME s_scm_peek_char
951 {
952 int c;
953 if (SCM_UNBNDP (port))
954 port = scm_cur_inp;
955 else
956 SCM_VALIDATE_OPINPORT (1,port);
957 c = scm_getc (port);
958 if (EOF == c)
959 return SCM_EOF_VAL;
960 scm_ungetc (c, port);
961 return SCM_MAKICHR (c);
962 }
963 #undef FUNC_NAME
964
965 SCM_DEFINE (scm_unread_char, "unread-char", 2, 0, 0,
966 (SCM cobj, SCM port),
967 "Place @var{char} in @var{port} so that it will be read by the\n"
968 "next read operation. If called multiple times, the unread characters\n"
969 "will be read again in last-in first-out order. If @var{port} is\n"
970 "not supplied, the current input port is used.")
971 #define FUNC_NAME s_scm_unread_char
972 {
973 int c;
974
975 SCM_VALIDATE_ICHR (1,cobj);
976 if (SCM_UNBNDP (port))
977 port = scm_cur_inp;
978 else
979 SCM_VALIDATE_OPINPORT (2,port);
980
981 c = SCM_ICHR (cobj);
982
983 scm_ungetc (c, port);
984 return cobj;
985 }
986 #undef FUNC_NAME
987
988 SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
989 (SCM str, SCM port),
990 "Place the string @var{str} in @var{port} so that its characters will be\n"
991 "read in subsequent read operations. If called multiple times, the\n"
992 "unread characters will be read again in last-in first-out order. If\n"
993 "@var{port} is not supplied, the current-input-port is used.")
994 #define FUNC_NAME s_scm_unread_string
995 {
996 SCM_VALIDATE_STRING (1,str);
997 if (SCM_UNBNDP (port))
998 port = scm_cur_inp;
999 else
1000 SCM_VALIDATE_OPINPORT (2,port);
1001
1002 scm_ungets (SCM_ROUCHARS (str), SCM_LENGTH (str), port);
1003
1004 return str;
1005 }
1006 #undef FUNC_NAME
1007
1008 SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1009 (SCM object, SCM offset, SCM whence),
1010 "Sets the current position of @var{fd/port} to the integer @var{offset},\n"
1011 "which is interpreted according to the value of @var{whence}.\n\n"
1012 "One of the following variables should be supplied\n"
1013 "for @var{whence}:\n"
1014 "@defvar SEEK_SET\n"
1015 "Seek from the beginning of the file.\n"
1016 "@end defvar\n"
1017 "@defvar SEEK_CUR\n"
1018 "Seek from the current position.\n"
1019 "@end defvar\n"
1020 "@defvar SEEK_END\n"
1021 "Seek from the end of the file.\n"
1022 "@end defvar\n\n"
1023 "If @var{fd/port} is a file descriptor, the underlying system call is\n"
1024 "@code{lseek}. @var{port} may be a string port.\n\n"
1025 "The value returned is the new position in the file. This means that\n"
1026 "the current position of a port can be obtained using:\n"
1027 "@smalllisp\n"
1028 "(seek port 0 SEEK_CUR)\n"
1029 "@end smalllisp")
1030 #define FUNC_NAME s_scm_seek
1031 {
1032 off_t off;
1033 off_t rv;
1034 int how;
1035
1036 object = SCM_COERCE_OUTPORT (object);
1037
1038 off = SCM_NUM2LONG (2,offset);
1039 SCM_VALIDATE_INUM_COPY (3,whence,how);
1040 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1041 SCM_OUT_OF_RANGE (3, whence);
1042 if (SCM_OPPORTP (object))
1043 {
1044 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
1045
1046 if (!ptob->seek)
1047 SCM_MISC_ERROR ("port is not seekable",
1048 scm_cons (object, SCM_EOL));
1049 else
1050 rv = ptob->seek (object, off, how);
1051 }
1052 else /* file descriptor?. */
1053 {
1054 SCM_VALIDATE_INUM (1,object);
1055 rv = lseek (SCM_INUM (object), off, how);
1056 if (rv == -1)
1057 SCM_SYSERROR;
1058 }
1059 return scm_long2num (rv);
1060 }
1061 #undef FUNC_NAME
1062
1063 SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1064 (SCM object, SCM length),
1065 "Truncates the object referred to by @var{obj} to at most @var{size} bytes.\n"
1066 "@var{obj} can be a string containing a file name or an integer file\n"
1067 "descriptor or a port. @var{size} may be omitted if @var{obj} is not\n"
1068 "a file name, in which case the truncation occurs at the current port.\n"
1069 "position.\n\n"
1070 "The return value is unspecified.")
1071 #define FUNC_NAME s_scm_truncate_file
1072 {
1073 int rv;
1074 off_t c_length;
1075
1076 /* object can be a port, fdes or filename. */
1077
1078 if (SCM_UNBNDP (length))
1079 {
1080 /* must supply length if object is a filename. */
1081 if (SCM_ROSTRINGP (object))
1082 SCM_MISC_ERROR("must supply length if OBJECT is a filename",SCM_EOL);
1083
1084 length = scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
1085 }
1086 c_length = SCM_NUM2LONG (2,length);
1087 if (c_length < 0)
1088 SCM_MISC_ERROR ("negative offset", SCM_EOL);
1089
1090 object = SCM_COERCE_OUTPORT (object);
1091 if (SCM_INUMP (object))
1092 {
1093 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1094 }
1095 else if (SCM_OPOUTPORTP (object))
1096 {
1097 scm_port *pt = SCM_PTAB_ENTRY (object);
1098 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
1099
1100 if (!ptob->truncate)
1101 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
1102 if (pt->rw_active == SCM_PORT_READ)
1103 scm_end_input (object);
1104 else if (pt->rw_active == SCM_PORT_WRITE)
1105 ptob->flush (object);
1106
1107 ptob->truncate (object, c_length);
1108 rv = 0;
1109 }
1110 else
1111 {
1112 SCM_VALIDATE_ROSTRING (1,object);
1113 SCM_COERCE_SUBSTR (object);
1114 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), c_length));
1115 }
1116 if (rv == -1)
1117 SCM_SYSERROR;
1118 return SCM_UNSPECIFIED;
1119 }
1120 #undef FUNC_NAME
1121
1122 SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1123 (SCM port),
1124 "")
1125 #define FUNC_NAME s_scm_port_line
1126 {
1127 port = SCM_COERCE_OUTPORT (port);
1128 SCM_VALIDATE_OPENPORT (1,port);
1129 return SCM_MAKINUM (SCM_LINUM (port));
1130 }
1131 #undef FUNC_NAME
1132
1133 SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1134 (SCM port, SCM line),
1135 "")
1136 #define FUNC_NAME s_scm_set_port_line_x
1137 {
1138 port = SCM_COERCE_OUTPORT (port);
1139 SCM_VALIDATE_OPENPORT (1,port);
1140 SCM_VALIDATE_INUM (2,line);
1141 return SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1142 }
1143 #undef FUNC_NAME
1144
1145 SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1146 (SCM port),
1147 "@deffnx primitive port-line [input-port]\n"
1148 "Return the current column number or line number of @var{input-port},\n"
1149 "using the current input port if none is specified. If the number is\n"
1150 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1151 "- i.e. the first character of the first line is line 0, column 0.\n"
1152 "(However, when you display a file position, for example in an error\n"
1153 "message, we recommand you add 1 to get 1-origin integers. This is\n"
1154 "because lines and column numbers traditionally start with 1, and that is\n"
1155 "what non-programmers will find most natural.)")
1156 #define FUNC_NAME s_scm_port_column
1157 {
1158 port = SCM_COERCE_OUTPORT (port);
1159 SCM_VALIDATE_OPENPORT (1,port);
1160 return SCM_MAKINUM (SCM_COL (port));
1161 }
1162 #undef FUNC_NAME
1163
1164 SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1165 (SCM port, SCM column),
1166 "@deffnx primitive set-port-line! [input-port] line\n"
1167 "Set the current column or line number of @var{input-port}, using the\n"
1168 "current input port if none is specified.")
1169 #define FUNC_NAME s_scm_set_port_column_x
1170 {
1171 port = SCM_COERCE_OUTPORT (port);
1172 SCM_VALIDATE_OPENPORT (1,port);
1173 SCM_VALIDATE_INUM (2,column);
1174 return SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1175 }
1176 #undef FUNC_NAME
1177
1178 SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1179 (SCM port),
1180 "Return the filename associated with @var{port}. This function returns\n"
1181 "the strings "standard input", "standard output" and "standard error"
1182 when called on the current input, output and error ports respectively.")
1183 #define FUNC_NAME s_scm_port_filename
1184 {
1185 port = SCM_COERCE_OUTPORT (port);
1186 SCM_VALIDATE_OPENPORT (1,port);
1187 return SCM_PTAB_ENTRY (port)->file_name;
1188 }
1189 #undef FUNC_NAME
1190
1191 SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1192 (SCM port, SCM filename),
1193 "Change the filename associated with @var{port}, using the current input\n"
1194 "port if none is specified. Note that this does not change the port's\n"
1195 "source of data, but only the value that is returned by\n"
1196 "@code{port-filename} and reported in diagnostic output.")
1197 #define FUNC_NAME s_scm_set_port_filename_x
1198 {
1199 port = SCM_COERCE_OUTPORT (port);
1200 SCM_VALIDATE_OPENPORT (1,port);
1201 /* We allow the user to set the filename to whatever he likes. */
1202 return SCM_PTAB_ENTRY (port)->file_name = filename;
1203 }
1204 #undef FUNC_NAME
1205
1206 #ifndef ttyname
1207 extern char * ttyname();
1208 #endif
1209
1210 void
1211 scm_print_port_mode (SCM exp, SCM port)
1212 {
1213 scm_puts (SCM_CLOSEDP (exp)
1214 ? "closed: "
1215 : (SCM_RDNG & SCM_CAR (exp)
1216 ? (SCM_WRTNG & SCM_CAR (exp)
1217 ? "input-output: "
1218 : "input: ")
1219 : (SCM_WRTNG & SCM_CAR (exp)
1220 ? "output: "
1221 : "bogus: ")),
1222 port);
1223 }
1224
1225 int
1226 scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
1227 {
1228 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1229 if (!type)
1230 type = "port";
1231 scm_puts ("#<", port);
1232 scm_print_port_mode (exp, port);
1233 scm_puts (type, port);
1234 scm_putc (' ', port);
1235 scm_intprint (SCM_CDR (exp), 16, port);
1236 scm_putc ('>', port);
1237 return 1;
1238 }
1239
1240 extern void scm_make_fptob ();
1241 extern void scm_make_stptob ();
1242 extern void scm_make_sfptob ();
1243
1244 void
1245 scm_ports_prehistory ()
1246 {
1247 scm_numptob = 0;
1248 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
1249
1250 /* WARNING: These scm_newptob calls must be done in this order.
1251 * They must agree with the port declarations in tags.h.
1252 */
1253 /* scm_tc16_fport = */ scm_make_fptob ();
1254 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1255 /* scm_tc16_strport = */ scm_make_stptob ();
1256 /* scm_tc16_sfport = */ scm_make_sfptob ();
1257 }
1258
1259 \f
1260
1261 /* Void ports. */
1262
1263 long scm_tc16_void_port = 0;
1264
1265 static void
1266 flush_void_port (SCM port)
1267 {
1268 }
1269
1270 static void
1271 end_input_void_port (SCM port, int offset)
1272 {
1273 }
1274
1275 static void
1276 write_void_port (SCM port, const void *data, size_t size)
1277 {
1278 }
1279
1280 SCM
1281 scm_void_port (char *mode_str)
1282 {
1283 int mode_bits;
1284 SCM answer;
1285 scm_port * pt;
1286
1287 SCM_NEWCELL (answer);
1288 SCM_DEFER_INTS;
1289 mode_bits = scm_mode_bits (mode_str);
1290 pt = scm_add_to_port_table (answer);
1291 SCM_SETPTAB_ENTRY (answer, pt);
1292 SCM_SETSTREAM (answer, 0);
1293 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
1294 SCM_ALLOW_INTS;
1295 return answer;
1296 }
1297
1298
1299 SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1300 (SCM mode),
1301 "Create and return a new void port. The @var{mode} argument describes\n"
1302 "the input/output modes for this port; for a description, see the\n"
1303 "documentation for @code{open-file} in @ref{File Ports}.")
1304 #define FUNC_NAME s_scm_sys_make_void_port
1305 {
1306 SCM_VALIDATE_ROSTRING (1,mode);
1307 SCM_COERCE_SUBSTR (mode);
1308 return scm_void_port (SCM_ROCHARS (mode));
1309 }
1310 #undef FUNC_NAME
1311
1312 \f
1313 /* Initialization. */
1314
1315 void
1316 scm_init_ports ()
1317 {
1318 /* lseek() symbols. */
1319 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1320 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1321 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1322
1323 scm_tc16_void_port = scm_make_port_type ("void", 0, write_void_port);
1324 #include "ports.x"
1325 }