]> git.donarmstrong.com Git - lilypond.git/blob - guile18/libguile/ports.c
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / libguile / ports.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
2  * 
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library 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 GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17
18
19 \f
20 /* Headers.  */
21
22 #define _LARGEFILE64_SOURCE      /* ask for stat64 etc */
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <fcntl.h>  /* for chsize on mingw */
31 #include <assert.h>
32
33 #include "libguile/_scm.h"
34 #include "libguile/async.h"
35 #include "libguile/eval.h"
36 #include "libguile/fports.h"  /* direct access for seek and truncate */
37 #include "libguile/objects.h"
38 #include "libguile/goops.h"
39 #include "libguile/smob.h"
40 #include "libguile/chars.h"
41 #include "libguile/dynwind.h"
42
43 #include "libguile/keywords.h"
44 #include "libguile/root.h"
45 #include "libguile/strings.h"
46 #include "libguile/mallocs.h"
47 #include "libguile/validate.h"
48 #include "libguile/ports.h"
49 #include "libguile/vectors.h"
50 #include "libguile/fluids.h"
51
52 #ifdef HAVE_STRING_H
53 #include <string.h>
54 #endif
55
56 #ifdef HAVE_MALLOC_H
57 #include <malloc.h>
58 #endif
59
60 #ifdef HAVE_IO_H
61 #include <io.h>
62 #endif
63
64 #ifdef HAVE_UNISTD_H
65 #include <unistd.h>
66 #endif
67
68 #ifdef HAVE_SYS_IOCTL_H
69 #include <sys/ioctl.h>
70 #endif
71
72 /* Mingw (version 3.4.5, circa 2006) has ftruncate as an alias for chsize
73    already, but have this code here in case that wasn't so in past versions,
74    or perhaps to help other minimal DOS environments.
75
76    gnulib ftruncate.c has code using fcntl F_CHSIZE and F_FREESP, which
77    might be possibilities if we've got other systems without ftruncate.  */
78
79 #if HAVE_CHSIZE && ! HAVE_FTRUNCATE
80 #define ftruncate(fd, size) chsize (fd, size)
81 #undef HAVE_FTRUNCATE
82 #define HAVE_FTRUNCATE 1
83 #endif
84
85 \f
86 /* The port kind table --- a dynamically resized array of port types.  */
87
88
89 /* scm_ptobs scm_numptob
90  * implement a dynamicly resized array of ptob records.
91  * Indexes into this table are used when generating type
92  * tags for smobjects (if you know a tag you can get an index and conversely).
93  */
94 scm_t_ptob_descriptor *scm_ptobs;
95 long scm_numptob;
96
97 /* GC marker for a port with stream of SCM type.  */
98 SCM 
99 scm_markstream (SCM ptr)
100 {
101   int openp;
102   openp = SCM_CELL_WORD_0 (ptr) & SCM_OPN;
103   if (openp)
104     return SCM_PACK (SCM_STREAM (ptr));
105   else
106     return SCM_BOOL_F;
107 }
108
109 /*
110  * We choose to use an interface similar to the smob interface with
111  * fill_input and write as standard fields, passed to the port
112  * type constructor, and optional fields set by setters.
113  */
114
115 static void
116 flush_port_default (SCM port SCM_UNUSED)
117 {
118 }
119
120 static void
121 end_input_default (SCM port SCM_UNUSED, int offset SCM_UNUSED)
122 {
123 }
124
125 static size_t
126 scm_port_free0 (SCM port)
127 {
128   return 0;
129 }
130
131 scm_t_bits
132 scm_make_port_type (char *name,
133                     int (*fill_input) (SCM port),
134                     void (*write) (SCM port, const void *data, size_t size))
135 {
136   char *tmp;
137   if (255 <= scm_numptob)
138     goto ptoberr;
139   SCM_CRITICAL_SECTION_START;
140   SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
141                                        (1 + scm_numptob)
142                                        * sizeof (scm_t_ptob_descriptor)));
143   if (tmp)
144     {
145       scm_ptobs = (scm_t_ptob_descriptor *) tmp;
146
147       scm_ptobs[scm_numptob].name = name;
148       scm_ptobs[scm_numptob].mark = 0;
149       scm_ptobs[scm_numptob].free = scm_port_free0;
150       scm_ptobs[scm_numptob].print = scm_port_print;
151       scm_ptobs[scm_numptob].equalp = 0;
152       scm_ptobs[scm_numptob].close = 0;
153
154       scm_ptobs[scm_numptob].write = write;
155       scm_ptobs[scm_numptob].flush = flush_port_default;
156
157       scm_ptobs[scm_numptob].end_input = end_input_default;
158       scm_ptobs[scm_numptob].fill_input = fill_input;
159       scm_ptobs[scm_numptob].input_waiting = 0;
160
161       scm_ptobs[scm_numptob].seek = 0;
162       scm_ptobs[scm_numptob].truncate = 0;
163
164       scm_numptob++;
165     }
166   SCM_CRITICAL_SECTION_END;
167   if (!tmp)
168     {
169     ptoberr:
170       scm_memory_error ("scm_make_port_type");
171     }
172   /* Make a class object if Goops is present */
173   if (scm_port_class)
174     scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
175   return scm_tc7_port + (scm_numptob - 1) * 256;
176 }
177
178 void
179 scm_set_port_mark (scm_t_bits tc, SCM (*mark) (SCM))
180 {
181   scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
182 }
183
184 void
185 scm_set_port_free (scm_t_bits tc, size_t (*free) (SCM))
186 {
187   scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
188 }
189
190 void
191 scm_set_port_print (scm_t_bits tc, int (*print) (SCM exp, SCM port,
192                                            scm_print_state *pstate))
193 {
194   scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
195 }
196
197 void
198 scm_set_port_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
199 {
200   scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
201 }
202
203 void
204 scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port))
205 {
206    scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
207 }
208
209 void
210 scm_set_port_end_input (scm_t_bits tc, void (*end_input) (SCM port, int offset))
211 {
212   scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
213 }
214
215 void
216 scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
217 {
218   scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
219 }
220
221 void
222 scm_set_port_seek (scm_t_bits tc, off_t (*seek) (SCM port,
223                                            off_t OFFSET,
224                                            int WHENCE))
225 {
226   scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
227 }
228
229 void
230 scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM port, off_t length))
231 {
232   scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
233 }
234
235 void
236 scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) (SCM))
237 {
238   scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
239 }
240
241 \f
242
243 SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0, 
244             (SCM port),
245             "Return @code{#t} if a character is ready on input @var{port}\n"
246             "and return @code{#f} otherwise.  If @code{char-ready?} returns\n"
247             "@code{#t} then the next @code{read-char} operation on\n"
248             "@var{port} is guaranteed not to hang.  If @var{port} is a file\n"
249             "port at end of file then @code{char-ready?} returns @code{#t}.\n"
250             "\n"
251             "@code{char-ready?} exists to make it possible for a\n"
252             "program to accept characters from interactive ports without\n"
253             "getting stuck waiting for input.  Any input editors associated\n"
254             "with such ports must make sure that characters whose existence\n"
255             "has been asserted by @code{char-ready?} cannot be rubbed out.\n"
256             "If @code{char-ready?} were to return @code{#f} at end of file,\n"
257             "a port at end of file would be indistinguishable from an\n"
258             "interactive port that has no ready characters.")
259 #define FUNC_NAME s_scm_char_ready_p
260 {
261   scm_t_port *pt;
262
263   if (SCM_UNBNDP (port))
264     port = scm_current_input_port ();
265   else
266     SCM_VALIDATE_OPINPORT (1, port);
267
268   pt = SCM_PTAB_ENTRY (port);
269
270   /* if the current read buffer is filled, or the
271      last pushed-back char has been read and the saved buffer is
272      filled, result is true.  */
273   if (pt->read_pos < pt->read_end 
274       || (pt->read_buf == pt->putback_buf
275           && pt->saved_read_pos < pt->saved_read_end))
276     return SCM_BOOL_T;
277   else
278     {
279       scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
280       
281       if (ptob->input_waiting)
282         return scm_from_bool(ptob->input_waiting (port));
283       else
284         return SCM_BOOL_T;
285     }
286 }
287 #undef FUNC_NAME
288
289 /* move up to read_len chars from port's putback and/or read buffers
290    into memory starting at dest.  returns the number of chars moved.  */
291 size_t scm_take_from_input_buffers (SCM port, char *dest, size_t read_len)
292 {
293   scm_t_port *pt = SCM_PTAB_ENTRY (port);
294   size_t chars_read = 0;
295   size_t from_buf = min (pt->read_end - pt->read_pos, read_len);
296
297   if (from_buf > 0)
298     {
299       memcpy (dest, pt->read_pos, from_buf);
300       pt->read_pos += from_buf;
301       chars_read += from_buf;
302       read_len -= from_buf;
303       dest += from_buf;
304     }
305
306   /* if putback was active, try the real input buffer too.  */
307   if (pt->read_buf == pt->putback_buf)
308     {
309       from_buf = min (pt->saved_read_end - pt->saved_read_pos, read_len);
310       if (from_buf > 0)
311         {
312           memcpy (dest, pt->saved_read_pos, from_buf);
313           pt->saved_read_pos += from_buf;
314           chars_read += from_buf;
315         }
316     }
317   return chars_read;
318 }
319
320 /* Clear a port's read buffers, returning the contents.  */
321 SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0, 
322             (SCM port),
323             "This procedure clears a port's input buffers, similar\n"
324             "to the way that force-output clears the output buffer.  The\n"
325             "contents of the buffers are returned as a single string, e.g.,\n"
326             "\n"
327             "@lisp\n"
328             "(define p (open-input-file ...))\n"
329             "(drain-input p) => empty string, nothing buffered yet.\n"
330             "(unread-char (read-char p) p)\n"
331             "(drain-input p) => initial chars from p, up to the buffer size.\n"
332             "@end lisp\n\n"
333             "Draining the buffers may be useful for cleanly finishing\n"
334             "buffered I/O so that the file descriptor can be used directly\n"
335             "for further input.")
336 #define FUNC_NAME s_scm_drain_input
337 {
338   SCM result;
339   char *data;
340   scm_t_port *pt;
341   long count;
342
343   SCM_VALIDATE_OPINPORT (1, port);
344   pt = SCM_PTAB_ENTRY (port);
345
346   count = pt->read_end - pt->read_pos;
347   if (pt->read_buf == pt->putback_buf)
348     count += pt->saved_read_end - pt->saved_read_pos;
349
350   result = scm_i_make_string (count, &data);
351   scm_take_from_input_buffers (port, data, count);
352   return result;
353 }
354 #undef FUNC_NAME
355
356 \f
357 /* Standard ports --- current input, output, error, and more(!).  */
358
359 static SCM cur_inport_fluid;
360 static SCM cur_outport_fluid;
361 static SCM cur_errport_fluid;
362 static SCM cur_loadport_fluid;
363
364 SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
365             (),
366             "Return the current input port.  This is the default port used\n"
367             "by many input procedures.  Initially, @code{current-input-port}\n"
368             "returns the @dfn{standard input} in Unix and C terminology.")
369 #define FUNC_NAME s_scm_current_input_port
370 {
371   return scm_fluid_ref (cur_inport_fluid);
372 }
373 #undef FUNC_NAME
374
375 SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
376             (),
377             "Return the current output port.  This is the default port used\n"
378             "by many output procedures.  Initially,\n"
379             "@code{current-output-port} returns the @dfn{standard output} in\n"
380             "Unix and C terminology.")
381 #define FUNC_NAME s_scm_current_output_port
382 {
383   return scm_fluid_ref (cur_outport_fluid);
384 }
385 #undef FUNC_NAME
386
387 SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
388            (),
389             "Return the port to which errors and warnings should be sent (the\n"
390             "@dfn{standard error} in Unix and C terminology).")
391 #define FUNC_NAME s_scm_current_error_port
392 {
393   return scm_fluid_ref (cur_errport_fluid);
394 }
395 #undef FUNC_NAME
396
397 SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
398             (),
399             "Return the current-load-port.\n"
400             "The load port is used internally by @code{primitive-load}.")
401 #define FUNC_NAME s_scm_current_load_port
402 {
403   return scm_fluid_ref (cur_loadport_fluid);
404 }
405 #undef FUNC_NAME
406
407 SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
408            (SCM port),
409             "@deffnx {Scheme Procedure} set-current-output-port port\n"
410             "@deffnx {Scheme Procedure} set-current-error-port port\n"
411             "Change the ports returned by @code{current-input-port},\n"
412             "@code{current-output-port} and @code{current-error-port}, respectively,\n"
413             "so that they use the supplied @var{port} for input or output.")
414 #define FUNC_NAME s_scm_set_current_input_port
415 {
416   SCM oinp = scm_fluid_ref (cur_inport_fluid);
417   SCM_VALIDATE_OPINPORT (1, port);
418   scm_fluid_set_x (cur_inport_fluid, port);
419   return oinp;
420 }
421 #undef FUNC_NAME
422
423
424 SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
425             (SCM port),
426             "Set the current default output port to @var{port}.")
427 #define FUNC_NAME s_scm_set_current_output_port
428 {
429   SCM ooutp = scm_fluid_ref (cur_outport_fluid);
430   port = SCM_COERCE_OUTPORT (port);
431   SCM_VALIDATE_OPOUTPORT (1, port);
432   scm_fluid_set_x (cur_outport_fluid, port);
433   return ooutp;
434 }
435 #undef FUNC_NAME
436
437
438 SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
439             (SCM port),
440             "Set the current default error port to @var{port}.")
441 #define FUNC_NAME s_scm_set_current_error_port
442 {
443   SCM oerrp = scm_fluid_ref (cur_errport_fluid);
444   port = SCM_COERCE_OUTPORT (port);
445   SCM_VALIDATE_OPOUTPORT (1, port);
446   scm_fluid_set_x (cur_errport_fluid, port);
447   return oerrp;
448 }
449 #undef FUNC_NAME
450
451 void
452 scm_dynwind_current_input_port (SCM port)
453 #define FUNC_NAME NULL
454 {
455   SCM_VALIDATE_OPINPORT (1, port);
456   scm_dynwind_fluid (cur_inport_fluid, port);
457 }
458 #undef FUNC_NAME
459
460 void
461 scm_dynwind_current_output_port (SCM port)
462 #define FUNC_NAME NULL
463 {
464   port = SCM_COERCE_OUTPORT (port);
465   SCM_VALIDATE_OPOUTPORT (1, port);
466   scm_dynwind_fluid (cur_outport_fluid, port);
467 }
468 #undef FUNC_NAME
469
470 void
471 scm_dynwind_current_error_port (SCM port)
472 #define FUNC_NAME NULL
473 {
474   port = SCM_COERCE_OUTPORT (port);
475   SCM_VALIDATE_OPOUTPORT (1, port);
476   scm_dynwind_fluid (cur_errport_fluid, port);
477 }
478 #undef FUNC_NAME
479
480 void
481 scm_i_dynwind_current_load_port (SCM port)
482 {
483   scm_dynwind_fluid (cur_loadport_fluid, port);
484 }
485
486 \f
487 /* The port table --- an array of pointers to ports.  */
488
489 scm_t_port **scm_i_port_table;
490
491 long scm_i_port_table_size = 0; /* Number of ports in scm_i_port_table.  */
492 long scm_i_port_table_room = 20;        /* Size of the array.  */
493
494 scm_i_pthread_mutex_t scm_i_port_table_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
495
496 /* This function is not and should not be thread safe. */
497
498 SCM
499 scm_new_port_table_entry (scm_t_bits tag)
500 #define FUNC_NAME "scm_new_port_table_entry"
501 {
502   /*
503     We initialize the cell to empty, this is in case scm_gc_calloc
504     triggers GC ; we don't want the GC to scan a half-finished Z.
505    */
506   
507   SCM z = scm_cons (SCM_EOL, SCM_EOL);
508   scm_t_port *entry = (scm_t_port *) scm_gc_calloc (sizeof (scm_t_port), "port");
509   if (scm_i_port_table_size == scm_i_port_table_room)
510     {
511       /* initial malloc is in gc.c.  this doesn't use scm_gc_malloc etc.,
512          since it can never be freed during gc.  */
513       void *newt = scm_realloc ((char *) scm_i_port_table,
514                                 (size_t) (sizeof (scm_t_port *)
515                                           * scm_i_port_table_room * 2));
516       scm_i_port_table = (scm_t_port **) newt;
517       scm_i_port_table_room *= 2;
518     }
519
520   entry->entry = scm_i_port_table_size;
521
522   entry->file_name = SCM_BOOL_F;
523   entry->rw_active = SCM_PORT_NEITHER;
524
525   scm_i_port_table[scm_i_port_table_size] = entry;
526   scm_i_port_table_size++;
527
528   entry->port = z;
529   SCM_SET_CELL_TYPE(z, tag);
530   SCM_SETPTAB_ENTRY(z, entry);
531   
532   return z;
533 }
534 #undef FUNC_NAME
535
536 #if SCM_ENABLE_DEPRECATED==1
537 SCM_API scm_t_port *
538 scm_add_to_port_table (SCM port)
539 {
540   SCM z = scm_new_port_table_entry (scm_tc7_port);
541   scm_t_port * pt = SCM_PTAB_ENTRY(z);
542
543   pt->port = port;
544   SCM_SETCAR(z, SCM_EOL);
545   SCM_SETCDR(z, SCM_EOL);
546   SCM_SETPTAB_ENTRY (port, pt);
547   return pt;
548 }
549 #endif
550
551
552 /* Remove a port from the table and destroy it.  */
553
554 /* This function is not and should not be thread safe. */
555
556 void
557 scm_remove_from_port_table (SCM port)
558 #define FUNC_NAME "scm_remove_from_port_table"
559 {
560   scm_t_port *p = SCM_PTAB_ENTRY (port);
561   long i = p->entry;
562
563   if (i >= scm_i_port_table_size)
564     SCM_MISC_ERROR ("Port not in table: ~S", scm_list_1 (port));
565   if (p->putback_buf)
566     scm_gc_free (p->putback_buf, p->putback_buf_size, "putback buffer");
567   scm_gc_free (p, sizeof (scm_t_port), "port");
568   /* Since we have just freed slot i we can shrink the table by moving
569      the last entry to that slot... */
570   if (i < scm_i_port_table_size - 1)
571     {
572       scm_i_port_table[i] = scm_i_port_table[scm_i_port_table_size - 1];
573       scm_i_port_table[i]->entry = i;
574     }
575   SCM_SETPTAB_ENTRY (port, 0);
576   scm_i_port_table_size--;
577 }
578 #undef FUNC_NAME
579
580
581 #ifdef GUILE_DEBUG
582 /* Functions for debugging.  */
583
584 SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
585             (),
586             "Return the number of ports in the port table.  @code{pt-size}\n"
587             "is only included in @code{--enable-guile-debug} builds.")
588 #define FUNC_NAME s_scm_pt_size
589 {
590   return scm_from_int (scm_i_port_table_size);
591 }
592 #undef FUNC_NAME
593
594 SCM_DEFINE (scm_pt_member, "pt-member", 1, 0, 0,
595             (SCM index),
596             "Return the port at @var{index} in the port table.\n"
597             "@code{pt-member} is only included in\n"
598             "@code{--enable-guile-debug} builds.")
599 #define FUNC_NAME s_scm_pt_member
600 {
601   size_t i = scm_to_size_t (index);
602   if (i >= scm_i_port_table_size)
603     return SCM_BOOL_F;
604   else
605     return scm_i_port_table[i]->port;
606 }
607 #undef FUNC_NAME
608 #endif
609
610 void
611 scm_port_non_buffer (scm_t_port *pt)
612 {
613   pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
614   pt->write_buf = pt->write_pos = &pt->shortbuf;
615   pt->read_buf_size = pt->write_buf_size = 1;
616   pt->write_end = pt->write_buf + pt->write_buf_size;
617 }
618
619 \f
620 /* Revealed counts --- an oddity inherited from SCSH.  */
621
622 /* Find a port in the table and return its revealed count.
623    Also used by the garbage collector.
624  */
625
626 int
627 scm_revealed_count (SCM port)
628 {
629   return SCM_REVEALED(port);
630 }
631
632
633
634 /* Return the revealed count for a port.  */
635
636 SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
637            (SCM port),
638             "Return the revealed count for @var{port}.")
639 #define FUNC_NAME s_scm_port_revealed
640 {
641   port = SCM_COERCE_OUTPORT (port);
642   SCM_VALIDATE_OPENPORT (1, port);
643   return scm_from_int (scm_revealed_count (port));
644 }
645 #undef FUNC_NAME
646
647 /* Set the revealed count for a port.  */
648 SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
649            (SCM port, SCM rcount),
650             "Sets the revealed count for a port to a given value.\n"
651             "The return value is unspecified.")
652 #define FUNC_NAME s_scm_set_port_revealed_x
653 {
654   port = SCM_COERCE_OUTPORT (port);
655   SCM_VALIDATE_OPENPORT (1, port);
656   SCM_REVEALED (port) = scm_to_int (rcount);
657   return SCM_UNSPECIFIED;
658 }
659 #undef FUNC_NAME
660
661
662 \f
663 /* Retrieving a port's mode.  */
664
665 /* Return the flags that characterize a port based on the mode
666  * string used to open a file for that port.
667  *
668  * See PORT FLAGS in scm.h
669  */
670
671 static long
672 scm_i_mode_bits_n (const char *modes, size_t n)
673 {
674   return (SCM_OPN
675           | (memchr (modes, 'r', n) || memchr (modes, '+', n) ? SCM_RDNG : 0)
676           | (   memchr (modes, 'w', n)
677              || memchr (modes, 'a', n)
678              || memchr (modes, '+', n) ? SCM_WRTNG : 0)
679           | (memchr (modes, '0', n) ? SCM_BUF0 : 0)
680           | (memchr (modes, 'l', n) ? SCM_BUFLINE : 0));
681 }
682
683 long
684 scm_mode_bits (char *modes)
685 {
686   return scm_i_mode_bits_n (modes, strlen (modes));
687 }
688
689 long
690 scm_i_mode_bits (SCM modes)
691 {
692   long bits;
693
694   if (!scm_is_string (modes))
695     scm_wrong_type_arg_msg (NULL, 0, modes, "string");
696
697   bits = scm_i_mode_bits_n (scm_i_string_chars (modes),
698                             scm_i_string_length (modes));
699   scm_remember_upto_here_1 (modes);
700   return bits;
701 }
702
703 /* Return the mode flags from an open port.
704  * Some modes such as "append" are only used when opening
705  * a file and are not returned here.  */
706
707 SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
708            (SCM port),
709             "Return the port modes associated with the open port @var{port}.\n"
710             "These will not necessarily be identical to the modes used when\n"
711             "the port was opened, since modes such as \"append\" which are\n"
712             "used only during port creation are not retained.")
713 #define FUNC_NAME s_scm_port_mode
714 {
715   char modes[4];
716   modes[0] = '\0';
717
718   port = SCM_COERCE_OUTPORT (port);
719   SCM_VALIDATE_OPPORT (1, port);
720   if (SCM_CELL_WORD_0 (port) & SCM_RDNG) {
721     if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
722       strcpy (modes, "r+");
723     else
724       strcpy (modes, "r");
725   }
726   else if (SCM_CELL_WORD_0 (port) & SCM_WRTNG)
727     strcpy (modes, "w");
728   if (SCM_CELL_WORD_0 (port) & SCM_BUF0)
729     strcat (modes, "0");
730   return scm_from_locale_string (modes);
731 }
732 #undef FUNC_NAME
733
734
735 \f
736 /* Closing ports.  */
737
738 /* scm_close_port
739  * Call the close operation on a port object. 
740  * see also scm_close.
741  */
742 SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
743            (SCM port),
744             "Close the specified port object.  Return @code{#t} if it\n"
745             "successfully closes a port or @code{#f} if it was already\n"
746             "closed.  An exception may be raised if an error occurs, for\n"
747             "example when flushing buffered output.  See also @ref{Ports and\n"
748             "File Descriptors, close}, for a procedure which can close file\n"
749             "descriptors.")
750 #define FUNC_NAME s_scm_close_port
751 {
752   size_t i;
753   int rv;
754
755   port = SCM_COERCE_OUTPORT (port);
756
757   SCM_VALIDATE_PORT (1, port);
758   if (SCM_CLOSEDP (port))
759     return SCM_BOOL_F;
760   i = SCM_PTOBNUM (port);
761   if (scm_ptobs[i].close)
762     rv = (scm_ptobs[i].close) (port);
763   else
764     rv = 0;
765   scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
766   scm_remove_from_port_table (port);
767   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
768   SCM_CLR_PORT_OPEN_FLAG (port);
769   return scm_from_bool (rv >= 0);
770 }
771 #undef FUNC_NAME
772
773 SCM_DEFINE (scm_close_input_port, "close-input-port", 1, 0, 0,
774            (SCM port),
775             "Close the specified input port object.  The routine has no effect if\n"
776             "the file has already been closed.  An exception may be raised if an\n"
777             "error occurs.  The value returned is unspecified.\n\n"
778             "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
779             "which can close file descriptors.")
780 #define FUNC_NAME s_scm_close_input_port
781 {
782   SCM_VALIDATE_INPUT_PORT (1, port);
783   scm_close_port (port);
784   return SCM_UNSPECIFIED;
785 }
786 #undef FUNC_NAME
787
788 SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
789            (SCM port),
790             "Close the specified output port object.  The routine has no effect if\n"
791             "the file has already been closed.  An exception may be raised if an\n"
792             "error occurs.  The value returned is unspecified.\n\n"
793             "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
794             "which can close file descriptors.")
795 #define FUNC_NAME s_scm_close_output_port
796 {
797   port = SCM_COERCE_OUTPORT (port);
798   SCM_VALIDATE_OUTPUT_PORT (1, port);
799   scm_close_port (port);
800   return SCM_UNSPECIFIED;
801 }
802 #undef FUNC_NAME
803
804 void
805 scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
806 {
807   long i;
808   size_t n;
809   SCM ports;
810
811   /* Even without pre-emptive multithreading, running arbitrary code
812      while scanning the port table is unsafe because the port table
813      can change arbitrarily (from a GC, for example).  So we first
814      collect the ports into a vector. -mvo */
815
816   scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
817   n = scm_i_port_table_size;
818   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
819
820   ports = scm_c_make_vector (n, SCM_BOOL_F);
821
822   scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
823   if (n > scm_i_port_table_size)
824     n = scm_i_port_table_size;
825   for (i = 0; i < n; i++)
826     SCM_SIMPLE_VECTOR_SET (ports, i, scm_i_port_table[i]->port);
827   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
828
829   for (i = 0; i < n; i++)
830     proc (data, SCM_SIMPLE_VECTOR_REF (ports, i));
831
832   scm_remember_upto_here_1 (ports);
833 }
834
835 SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
836             (SCM proc),
837             "Apply @var{proc} to each port in the Guile port table\n"
838             "in turn.  The return value is unspecified.  More specifically,\n"
839             "@var{proc} is applied exactly once to every port that exists\n"
840             "in the system at the time @var{port-for-each} is invoked.\n"
841             "Changes to the port table while @var{port-for-each} is running\n"
842             "have no effect as far as @var{port-for-each} is concerned.") 
843 #define FUNC_NAME s_scm_port_for_each
844 {
845   SCM_VALIDATE_PROC (1, proc);
846
847   scm_c_port_for_each ((void (*)(void*,SCM))scm_call_1, proc);
848   return SCM_UNSPECIFIED;
849 }
850 #undef FUNC_NAME
851
852
853 \f
854 /* Utter miscellany.  Gosh, we should clean this up some time.  */
855
856 SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
857            (SCM x),
858             "Return @code{#t} if @var{x} is an input port, otherwise return\n"
859             "@code{#f}.  Any object satisfying this predicate also satisfies\n"
860             "@code{port?}.")
861 #define FUNC_NAME s_scm_input_port_p
862 {
863   return scm_from_bool (SCM_INPUT_PORT_P (x));
864 }
865 #undef FUNC_NAME
866
867 SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
868            (SCM x),
869             "Return @code{#t} if @var{x} is an output port, otherwise return\n"
870             "@code{#f}.  Any object satisfying this predicate also satisfies\n"
871             "@code{port?}.")
872 #define FUNC_NAME s_scm_output_port_p
873 {
874   x = SCM_COERCE_OUTPORT (x);
875   return scm_from_bool (SCM_OUTPUT_PORT_P (x));
876 }
877 #undef FUNC_NAME
878
879 SCM_DEFINE (scm_port_p, "port?", 1, 0, 0,
880             (SCM x),
881             "Return a boolean indicating whether @var{x} is a port.\n"
882             "Equivalent to @code{(or (input-port? @var{x}) (output-port?\n"
883             "@var{x}))}.")
884 #define FUNC_NAME s_scm_port_p
885 {
886   return scm_from_bool (SCM_PORTP (x));
887 }
888 #undef FUNC_NAME
889
890 SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
891            (SCM port),
892             "Return @code{#t} if @var{port} is closed or @code{#f} if it is\n"
893             "open.")
894 #define FUNC_NAME s_scm_port_closed_p
895 {
896   SCM_VALIDATE_PORT (1, port);
897   return scm_from_bool (!SCM_OPPORTP (port));
898 }
899 #undef FUNC_NAME
900
901 SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
902            (SCM x),
903             "Return @code{#t} if @var{x} is an end-of-file object; otherwise\n"
904             "return @code{#f}.")
905 #define FUNC_NAME s_scm_eof_object_p
906 {
907   return scm_from_bool(SCM_EOF_OBJECT_P (x));
908 }
909 #undef FUNC_NAME
910
911 SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
912            (SCM port),
913             "Flush the specified output port, or the current output port if @var{port}\n"
914             "is omitted.  The current output buffer contents are passed to the\n"
915             "underlying port implementation (e.g., in the case of fports, the\n"
916             "data will be written to the file and the output buffer will be cleared.)\n"
917             "It has no effect on an unbuffered port.\n\n"
918             "The return value is unspecified.")
919 #define FUNC_NAME s_scm_force_output
920 {
921   if (SCM_UNBNDP (port))
922     port = scm_current_output_port ();
923   else
924     {
925       port = SCM_COERCE_OUTPORT (port);
926       SCM_VALIDATE_OPOUTPORT (1, port);
927     }
928   scm_flush (port);
929   return SCM_UNSPECIFIED;
930 }
931 #undef FUNC_NAME
932
933 SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
934             (),
935             "Equivalent to calling @code{force-output} on\n"
936             "all open output ports.  The return value is unspecified.")
937 #define FUNC_NAME s_scm_flush_all_ports
938 {
939   size_t i;
940
941   scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
942   for (i = 0; i < scm_i_port_table_size; i++)
943     {
944       if (SCM_OPOUTPORTP (scm_i_port_table[i]->port))
945         scm_flush (scm_i_port_table[i]->port);
946     }
947   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
948   return SCM_UNSPECIFIED;
949 }
950 #undef FUNC_NAME
951
952 SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
953            (SCM port),
954             "Return the next character available from @var{port}, updating\n"
955             "@var{port} to point to the following character.  If no more\n"
956             "characters are available, the end-of-file object is returned.")
957 #define FUNC_NAME s_scm_read_char
958 {
959   int c;
960   if (SCM_UNBNDP (port))
961     port = scm_current_input_port ();
962   SCM_VALIDATE_OPINPORT (1, port);
963   c = scm_getc (port);
964   if (EOF == c)
965     return SCM_EOF_VAL;
966   return SCM_MAKE_CHAR (c);
967 }
968 #undef FUNC_NAME
969
970 /* this should only be called when the read buffer is empty.  it
971    tries to refill the read buffer.  it returns the first char from
972    the port, which is either EOF or *(pt->read_pos).  */
973 int
974 scm_fill_input (SCM port)
975 {
976   scm_t_port *pt = SCM_PTAB_ENTRY (port);
977
978   assert (pt->read_pos == pt->read_end);
979
980   if (pt->read_buf == pt->putback_buf)
981     {
982       /* finished reading put-back chars.  */
983       pt->read_buf = pt->saved_read_buf;
984       pt->read_pos = pt->saved_read_pos;
985       pt->read_end = pt->saved_read_end;
986       pt->read_buf_size = pt->saved_read_buf_size;
987       if (pt->read_pos < pt->read_end)
988         return *(pt->read_pos);
989     }
990   return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
991 }
992
993
994 /* scm_lfwrite
995  *
996  * This function differs from scm_c_write; it updates port line and
997  * column. */
998
999 void 
1000 scm_lfwrite (const char *ptr, size_t size, SCM port)
1001 {
1002   scm_t_port *pt = SCM_PTAB_ENTRY (port);
1003   scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
1004
1005   if (pt->rw_active == SCM_PORT_READ)
1006     scm_end_input (port);
1007
1008   ptob->write (port, ptr, size);
1009
1010   for (; size; ptr++, size--) {
1011     if (*ptr == '\a') {
1012     }
1013     else if (*ptr == '\b') {
1014       SCM_DECCOL(port);
1015     }
1016     else if (*ptr == '\n') {
1017       SCM_INCLINE(port);
1018     }
1019     else if (*ptr == '\r') {
1020       SCM_ZEROCOL(port);
1021     }
1022     else if (*ptr == '\t') {
1023       SCM_TABCOL(port);
1024     }
1025     else {
1026       SCM_INCCOL(port);
1027     }
1028   }
1029
1030   if (pt->rw_random)
1031     pt->rw_active = SCM_PORT_WRITE;
1032 }
1033
1034 /* scm_c_read
1035  *
1036  * Used by an application to read arbitrary number of bytes from an
1037  * SCM port.  Same semantics as libc read, except that scm_c_read only
1038  * returns less than SIZE bytes if at end-of-file.
1039  *
1040  * Warning: Doesn't update port line and column counts!  */
1041
1042 /* This structure, and the following swap_buffer function, are used
1043    for temporarily swapping a port's own read buffer, and the buffer
1044    that the caller of scm_c_read provides. */
1045 struct port_and_swap_buffer
1046 {
1047   scm_t_port *pt;
1048   unsigned char *buffer;
1049   size_t size;
1050 };
1051
1052 static void
1053 swap_buffer (void *data)
1054 {
1055   struct port_and_swap_buffer *psb = (struct port_and_swap_buffer *) data;
1056   unsigned char *old_buf = psb->pt->read_buf;
1057   size_t old_size = psb->pt->read_buf_size;
1058
1059   /* Make the port use (buffer, size) from the struct. */
1060   psb->pt->read_pos = psb->pt->read_buf = psb->pt->read_end = psb->buffer;
1061   psb->pt->read_buf_size = psb->size;
1062
1063   /* Save the port's old (buffer, size) in the struct. */
1064   psb->buffer = old_buf;
1065   psb->size = old_size;
1066 }
1067
1068 size_t
1069 scm_c_read (SCM port, void *buffer, size_t size)
1070 #define FUNC_NAME "scm_c_read"
1071 {
1072   scm_t_port *pt;
1073   size_t n_read = 0, n_available;
1074   struct port_and_swap_buffer psb;
1075
1076   SCM_VALIDATE_OPINPORT (1, port);
1077
1078   pt = SCM_PTAB_ENTRY (port);
1079   if (pt->rw_active == SCM_PORT_WRITE)
1080     scm_ptobs[SCM_PTOBNUM (port)].flush (port);
1081
1082   if (pt->rw_random)
1083     pt->rw_active = SCM_PORT_READ;
1084
1085   /* Take bytes first from the port's read buffer. */
1086   if (pt->read_pos < pt->read_end)
1087     {
1088       n_available = min (size, pt->read_end - pt->read_pos);
1089       memcpy (buffer, pt->read_pos, n_available);
1090       buffer = (char *) buffer + n_available;
1091       pt->read_pos += n_available;
1092       n_read += n_available;
1093       size -= n_available;
1094     }
1095
1096   /* Avoid the scm_dynwind_* costs if we now have enough data. */
1097   if (size == 0)
1098     return n_read;
1099
1100   /* Now we will call scm_fill_input repeatedly until we have read the
1101      requested number of bytes.  (Note that a single scm_fill_input
1102      call does not guarantee to fill the whole of the port's read
1103      buffer.) */
1104   if (pt->read_buf_size <= 1)
1105     {
1106       /* The port that we are reading from is unbuffered - i.e. does
1107          not have its own persistent buffer - but we have a buffer,
1108          provided by our caller, that is the right size for the data
1109          that is wanted.  For the following scm_fill_input calls,
1110          therefore, we use the buffer in hand as the port's read
1111          buffer.
1112
1113          We need to make sure that the port's normal (1 byte) buffer
1114          is reinstated in case one of the scm_fill_input () calls
1115          throws an exception; we use the scm_dynwind_* API to achieve
1116          that. */
1117       psb.pt = pt;
1118       psb.buffer = buffer;
1119       psb.size = size;
1120       scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
1121       scm_dynwind_rewind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1122       scm_dynwind_unwind_handler (swap_buffer, &psb, SCM_F_WIND_EXPLICITLY);
1123
1124       /* Call scm_fill_input until we have all the bytes that we need,
1125          or we hit EOF. */
1126       while (pt->read_buf_size && (scm_fill_input (port) != EOF))
1127         {
1128           pt->read_buf_size -= (pt->read_end - pt->read_pos);
1129           pt->read_pos = pt->read_buf = pt->read_end;
1130         }
1131       n_read += pt->read_buf - (unsigned char *) buffer;
1132
1133       /* Reinstate the port's normal buffer. */
1134       scm_dynwind_end ();
1135     }
1136   else
1137     {
1138       /* The port has its own buffer.  It is important that we use it,
1139          even if it happens to be smaller than our caller's buffer, so
1140          that a custom port implementation's entry points (in
1141          particular, fill_input) can rely on the buffer always being
1142          the same as they first set up. */
1143       while (size && (scm_fill_input (port) != EOF))
1144         {
1145           n_available = min (size, pt->read_end - pt->read_pos);
1146           memcpy (buffer, pt->read_pos, n_available);
1147           buffer = (char *) buffer + n_available;
1148           pt->read_pos += n_available;
1149           n_read += n_available;
1150           size -= n_available;
1151         } 
1152     }
1153
1154   return n_read;
1155 }
1156 #undef FUNC_NAME
1157
1158 /* scm_c_write
1159  *
1160  * Used by an application to write arbitrary number of bytes to an SCM
1161  * port.  Similar semantics as libc write.  However, unlike libc
1162  * write, scm_c_write writes the requested number of bytes and has no
1163  * return value.
1164  *
1165  * Warning: Doesn't update port line and column counts!
1166  */
1167
1168 void
1169 scm_c_write (SCM port, const void *ptr, size_t size)
1170 #define FUNC_NAME "scm_c_write"
1171 {
1172   scm_t_port *pt;
1173   scm_t_ptob_descriptor *ptob;
1174
1175   SCM_VALIDATE_OPOUTPORT (1, port);
1176
1177   pt = SCM_PTAB_ENTRY (port);
1178   ptob = &scm_ptobs[SCM_PTOBNUM (port)];
1179
1180   if (pt->rw_active == SCM_PORT_READ)
1181     scm_end_input (port);
1182
1183   ptob->write (port, ptr, size);
1184
1185   if (pt->rw_random)
1186     pt->rw_active = SCM_PORT_WRITE;
1187 }
1188 #undef FUNC_NAME
1189
1190 void 
1191 scm_flush (SCM port)
1192 {
1193   long i = SCM_PTOBNUM (port);
1194   (scm_ptobs[i].flush) (port);
1195 }
1196
1197 void
1198 scm_end_input (SCM port)
1199 {
1200   long offset;
1201   scm_t_port *pt = SCM_PTAB_ENTRY (port);
1202
1203   if (pt->read_buf == pt->putback_buf)
1204     {
1205       offset = pt->read_end - pt->read_pos;
1206       pt->read_buf = pt->saved_read_buf;
1207       pt->read_pos = pt->saved_read_pos;
1208       pt->read_end = pt->saved_read_end;
1209       pt->read_buf_size = pt->saved_read_buf_size;
1210     }
1211   else
1212     offset = 0;
1213
1214   scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
1215 }
1216
1217 \f
1218
1219
1220 void 
1221 scm_ungetc (int c, SCM port)
1222 #define FUNC_NAME "scm_ungetc"
1223 {
1224   scm_t_port *pt = SCM_PTAB_ENTRY (port);
1225
1226   if (pt->read_buf == pt->putback_buf)
1227     /* already using the put-back buffer.  */
1228     {
1229       /* enlarge putback_buf if necessary.  */
1230       if (pt->read_end == pt->read_buf + pt->read_buf_size
1231           && pt->read_buf == pt->read_pos)
1232         {
1233           size_t new_size = pt->read_buf_size * 2;
1234           unsigned char *tmp = (unsigned char *)
1235             scm_gc_realloc (pt->putback_buf, pt->read_buf_size, new_size,
1236                             "putback buffer");
1237
1238           pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
1239           pt->read_end = pt->read_buf + pt->read_buf_size;
1240           pt->read_buf_size = pt->putback_buf_size = new_size;
1241         }
1242
1243       /* shift any existing bytes to buffer + 1.  */
1244       if (pt->read_pos == pt->read_end)
1245         pt->read_end = pt->read_buf + 1;
1246       else if (pt->read_pos != pt->read_buf + 1)
1247         {
1248           int count = pt->read_end - pt->read_pos;
1249
1250           memmove (pt->read_buf + 1, pt->read_pos, count);
1251           pt->read_end = pt->read_buf + 1 + count;
1252         }
1253
1254       pt->read_pos = pt->read_buf;
1255     }
1256   else
1257     /* switch to the put-back buffer.  */
1258     {
1259       if (pt->putback_buf == NULL)
1260         {
1261           pt->putback_buf
1262             = (unsigned char *) scm_gc_malloc (SCM_INITIAL_PUTBACK_BUF_SIZE,
1263                                                "putback buffer");
1264           pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
1265         }
1266
1267       pt->saved_read_buf = pt->read_buf;
1268       pt->saved_read_pos = pt->read_pos;
1269       pt->saved_read_end = pt->read_end;
1270       pt->saved_read_buf_size = pt->read_buf_size;
1271
1272       pt->read_pos = pt->read_buf = pt->putback_buf;
1273       pt->read_end = pt->read_buf + 1;
1274       pt->read_buf_size = pt->putback_buf_size;
1275     }
1276
1277   *pt->read_buf = c;
1278
1279   if (pt->rw_random)
1280     pt->rw_active = SCM_PORT_READ;
1281
1282   if (c == '\n')
1283     {
1284       /* What should col be in this case?
1285        * We'll leave it at -1.
1286        */
1287       SCM_LINUM (port) -= 1;
1288     }
1289   else
1290     SCM_COL(port) -= 1;
1291 }
1292 #undef FUNC_NAME
1293
1294
1295 void 
1296 scm_ungets (const char *s, int n, SCM port)
1297 {
1298   /* This is simple minded and inefficient, but unreading strings is
1299    * probably not a common operation, and remember that line and
1300    * column numbers have to be handled...
1301    *
1302    * Please feel free to write an optimized version!
1303    */
1304   while (n--)
1305     scm_ungetc (s[n], port);
1306 }
1307
1308
1309 SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1310            (SCM port),
1311             "Return the next character available from @var{port},\n"
1312             "@emph{without} updating @var{port} to point to the following\n"
1313             "character.  If no more characters are available, the\n"
1314             "end-of-file object is returned.\n"
1315             "\n"
1316             "The value returned by\n"
1317             "a call to @code{peek-char} is the same as the value that would\n"
1318             "have been returned by a call to @code{read-char} on the same\n"
1319             "port.  The only difference is that the very next call to\n"
1320             "@code{read-char} or @code{peek-char} on that @var{port} will\n"
1321             "return the value returned by the preceding call to\n"
1322             "@code{peek-char}.  In particular, a call to @code{peek-char} on\n"
1323             "an interactive port will hang waiting for input whenever a call\n"
1324             "to @code{read-char} would have hung.")
1325 #define FUNC_NAME s_scm_peek_char
1326 {
1327   int c, column;
1328   if (SCM_UNBNDP (port))
1329     port = scm_current_input_port ();
1330   else
1331     SCM_VALIDATE_OPINPORT (1, port);
1332   column = SCM_COL(port);
1333   c = scm_getc (port);
1334   if (EOF == c)
1335     return SCM_EOF_VAL;
1336   scm_ungetc (c, port);
1337   SCM_COL(port) = column;
1338   return SCM_MAKE_CHAR (c);
1339 }
1340 #undef FUNC_NAME
1341
1342 SCM_DEFINE (scm_unread_char, "unread-char", 1, 1, 0,
1343             (SCM cobj, SCM port),
1344             "Place @var{char} in @var{port} so that it will be read by the\n"
1345             "next read operation.  If called multiple times, the unread characters\n"
1346             "will be read again in last-in first-out order.  If @var{port} is\n"
1347             "not supplied, the current input port is used.")
1348 #define FUNC_NAME s_scm_unread_char
1349 {
1350   int c;
1351
1352   SCM_VALIDATE_CHAR (1, cobj);
1353   if (SCM_UNBNDP (port))
1354     port = scm_current_input_port ();
1355   else
1356     SCM_VALIDATE_OPINPORT (2, port);
1357
1358   c = SCM_CHAR (cobj);
1359
1360   scm_ungetc (c, port);
1361   return cobj;
1362 }
1363 #undef FUNC_NAME
1364
1365 SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1366             (SCM str, SCM port),
1367             "Place the string @var{str} in @var{port} so that its characters will be\n"
1368             "read in subsequent read operations.  If called multiple times, the\n"
1369             "unread characters will be read again in last-in first-out order.  If\n"
1370             "@var{port} is not supplied, the current-input-port is used.")
1371 #define FUNC_NAME s_scm_unread_string
1372 {
1373   SCM_VALIDATE_STRING (1, str);
1374   if (SCM_UNBNDP (port))
1375     port = scm_current_input_port ();
1376   else
1377     SCM_VALIDATE_OPINPORT (2, port);
1378
1379   scm_ungets (scm_i_string_chars (str), scm_i_string_length (str), port);
1380   
1381   return str;
1382 }
1383 #undef FUNC_NAME
1384
1385 SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1386             (SCM fd_port, SCM offset, SCM whence),
1387             "Sets the current position of @var{fd/port} to the integer\n"
1388             "@var{offset}, which is interpreted according to the value of\n"
1389             "@var{whence}.\n"
1390             "\n"
1391             "One of the following variables should be supplied for\n"
1392             "@var{whence}:\n"
1393             "@defvar SEEK_SET\n"
1394             "Seek from the beginning of the file.\n"
1395             "@end defvar\n"
1396             "@defvar SEEK_CUR\n"
1397             "Seek from the current position.\n"
1398             "@end defvar\n"
1399             "@defvar SEEK_END\n"
1400             "Seek from the end of the file.\n"
1401             "@end defvar\n"
1402             "If @var{fd/port} is a file descriptor, the underlying system\n"
1403             "call is @code{lseek}.  @var{port} may be a string port.\n"
1404             "\n"
1405             "The value returned is the new position in the file.  This means\n"
1406             "that the current position of a port can be obtained using:\n"
1407             "@lisp\n"
1408             "(seek port 0 SEEK_CUR)\n"
1409             "@end lisp")
1410 #define FUNC_NAME s_scm_seek
1411 {
1412   int how;
1413
1414   fd_port = SCM_COERCE_OUTPORT (fd_port);
1415
1416   how = scm_to_int (whence);
1417   if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1418     SCM_OUT_OF_RANGE (3, whence);
1419
1420   if (SCM_OPFPORTP (fd_port))
1421     {
1422       /* go direct to fport code to allow 64-bit offsets */
1423       return scm_i_fport_seek (fd_port, offset, how);
1424     }
1425   else if (SCM_OPPORTP (fd_port))
1426     {
1427       scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (fd_port);
1428       off_t off = scm_to_off_t (offset);
1429       off_t rv;
1430
1431       if (!ptob->seek)
1432         SCM_MISC_ERROR ("port is not seekable", 
1433                         scm_cons (fd_port, SCM_EOL));
1434       else
1435         rv = ptob->seek (fd_port, off, how);
1436       return scm_from_off_t (rv);
1437     }
1438   else /* file descriptor?.  */
1439     {
1440       off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
1441       off_t_or_off64_t rv;
1442       rv = lseek_or_lseek64 (scm_to_int (fd_port), off, how);
1443       if (rv == -1)
1444         SCM_SYSERROR;
1445       return scm_from_off_t_or_off64_t (rv);
1446     }
1447 }
1448 #undef FUNC_NAME
1449
1450 #ifndef O_BINARY
1451 #define O_BINARY 0
1452 #endif
1453
1454 /* Mingw has ftruncate(), perhaps implemented above using chsize, but
1455    doesn't have the filename version truncate(), hence this code.  */
1456 #if HAVE_FTRUNCATE && ! HAVE_TRUNCATE
1457 static int
1458 truncate (const char *file, off_t length)
1459 {
1460   int ret, fdes;
1461
1462   fdes = open (file, O_BINARY | O_WRONLY);
1463   if (fdes == -1)
1464     return -1;
1465
1466   ret = ftruncate (fdes, length);
1467   if (ret == -1)
1468     {
1469       int save_errno = errno;
1470       close (fdes);
1471       errno = save_errno;
1472       return -1;
1473     }
1474
1475   return close (fdes);
1476 }
1477 #endif /* HAVE_FTRUNCATE && ! HAVE_TRUNCATE */
1478
1479 SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1480             (SCM object, SCM length),
1481             "Truncate @var{file} to @var{length} bytes.  @var{file} can be a\n"
1482             "filename string, a port object, or an integer file descriptor.\n"
1483             "The return value is unspecified.\n"
1484             "\n"
1485             "For a port or file descriptor @var{length} can be omitted, in\n"
1486             "which case the file is truncated at the current position (per\n"
1487             "@code{ftell} above).\n"
1488             "\n"
1489             "On most systems a file can be extended by giving a length\n"
1490             "greater than the current size, but this is not mandatory in the\n"
1491             "POSIX standard.")
1492 #define FUNC_NAME s_scm_truncate_file
1493 {
1494   int rv;
1495
1496   /* "object" can be a port, fdes or filename.
1497
1498      Negative "length" makes no sense, but it's left to truncate() or
1499      ftruncate() to give back an error for that (normally EINVAL).
1500      */
1501
1502   if (SCM_UNBNDP (length))
1503     {
1504       /* must supply length if object is a filename.  */
1505       if (scm_is_string (object))
1506         SCM_MISC_ERROR("must supply length if OBJECT is a filename", SCM_EOL);
1507       
1508       length = scm_seek (object, SCM_INUM0, scm_from_int (SEEK_CUR));
1509     }
1510
1511   object = SCM_COERCE_OUTPORT (object);
1512   if (scm_is_integer (object))
1513     {
1514       off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
1515       SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
1516                                                   c_length));
1517     }
1518   else if (SCM_OPOUTFPORTP (object))
1519     {
1520       /* go direct to fport code to allow 64-bit offsets */
1521       rv = scm_i_fport_truncate (object, length);
1522     }
1523   else if (SCM_OPOUTPORTP (object))
1524     {
1525       off_t c_length = scm_to_off_t (length);
1526       scm_t_port *pt = SCM_PTAB_ENTRY (object);
1527       scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
1528       
1529       if (!ptob->truncate)
1530         SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
1531       if (pt->rw_active == SCM_PORT_READ)
1532         scm_end_input (object);
1533       else if (pt->rw_active == SCM_PORT_WRITE)
1534         ptob->flush (object);
1535       
1536       ptob->truncate (object, c_length);
1537       rv = 0;
1538     }
1539   else
1540     {
1541       off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
1542       char *str = scm_to_locale_string (object);
1543       int eno;
1544       SCM_SYSCALL (rv = truncate_or_truncate64 (str, c_length));
1545       eno = errno;
1546       free (str);
1547       errno = eno;
1548     }
1549   if (rv == -1)
1550     SCM_SYSERROR;
1551   return SCM_UNSPECIFIED;
1552 }
1553 #undef FUNC_NAME
1554
1555 SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1556             (SCM port),
1557             "Return the current line number for @var{port}.\n"
1558             "\n"
1559             "The first line of a file is 0.  But you might want to add 1\n"
1560             "when printing line numbers, since starting from 1 is\n"
1561             "traditional in error messages, and likely to be more natural to\n"
1562             "non-programmers.")
1563 #define FUNC_NAME s_scm_port_line
1564 {
1565   port = SCM_COERCE_OUTPORT (port);
1566   SCM_VALIDATE_OPENPORT (1, port);
1567   return scm_from_long (SCM_LINUM (port));
1568 }
1569 #undef FUNC_NAME
1570
1571 SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1572             (SCM port, SCM line),
1573             "Set the current line number for @var{port} to @var{line}.  The\n"
1574             "first line of a file is 0.")
1575 #define FUNC_NAME s_scm_set_port_line_x
1576 {
1577   port = SCM_COERCE_OUTPORT (port);
1578   SCM_VALIDATE_OPENPORT (1, port);
1579   SCM_PTAB_ENTRY (port)->line_number = scm_to_long (line);
1580   return SCM_UNSPECIFIED;
1581 }
1582 #undef FUNC_NAME
1583
1584 SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1585             (SCM port),
1586             "Return the current column number of @var{port}.\n"
1587             "If the number is\n"
1588             "unknown, the result is #f.  Otherwise, the result is a 0-origin integer\n"
1589             "- i.e. the first character of the first line is line 0, column 0.\n"
1590             "(However, when you display a file position, for example in an error\n"
1591             "message, we recommend you add 1 to get 1-origin integers.  This is\n"
1592             "because lines and column numbers traditionally start with 1, and that is\n"
1593             "what non-programmers will find most natural.)")
1594 #define FUNC_NAME s_scm_port_column
1595 {
1596   port = SCM_COERCE_OUTPORT (port);
1597   SCM_VALIDATE_OPENPORT (1, port);
1598   return scm_from_int (SCM_COL (port));
1599 }
1600 #undef FUNC_NAME
1601
1602 SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1603             (SCM port, SCM column),
1604             "Set the current column of @var{port}.  Before reading the first\n"
1605             "character on a line the column should be 0.")
1606 #define FUNC_NAME s_scm_set_port_column_x
1607 {
1608   port = SCM_COERCE_OUTPORT (port);
1609   SCM_VALIDATE_OPENPORT (1, port);
1610   SCM_PTAB_ENTRY (port)->column_number = scm_to_int (column);
1611   return SCM_UNSPECIFIED;
1612 }
1613 #undef FUNC_NAME
1614
1615 SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1616             (SCM port),
1617             "Return the filename associated with @var{port}.  This function returns\n"
1618             "the strings \"standard input\", \"standard output\" and \"standard error\"\n"
1619             "when called on the current input, output and error ports respectively.")
1620 #define FUNC_NAME s_scm_port_filename
1621 {
1622   port = SCM_COERCE_OUTPORT (port);
1623   SCM_VALIDATE_OPENPORT (1, port);
1624   return SCM_FILENAME (port);
1625 }
1626 #undef FUNC_NAME
1627
1628 SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1629             (SCM port, SCM filename),
1630             "Change the filename associated with @var{port}, using the current input\n"
1631             "port if none is specified.  Note that this does not change the port's\n"
1632             "source of data, but only the value that is returned by\n"
1633             "@code{port-filename} and reported in diagnostic output.")
1634 #define FUNC_NAME s_scm_set_port_filename_x
1635 {
1636   port = SCM_COERCE_OUTPORT (port);
1637   SCM_VALIDATE_OPENPORT (1, port);
1638   /* We allow the user to set the filename to whatever he likes.  */
1639   SCM_SET_FILENAME (port, filename);
1640   return SCM_UNSPECIFIED;
1641 }
1642 #undef FUNC_NAME
1643
1644 void
1645 scm_print_port_mode (SCM exp, SCM port)
1646 {
1647   scm_puts (SCM_CLOSEDP (exp)
1648             ? "closed: "
1649             : (SCM_RDNG & SCM_CELL_WORD_0 (exp)
1650                ? (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
1651                   ? "input-output: "
1652                   : "input: ")
1653                : (SCM_WRTNG & SCM_CELL_WORD_0 (exp)
1654                   ? "output: "
1655                   : "bogus: ")),
1656             port);
1657 }
1658
1659 int
1660 scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
1661 {
1662   char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1663   if (!type)
1664     type = "port";
1665   scm_puts ("#<", port);
1666   scm_print_port_mode (exp, port);
1667   scm_puts (type, port);
1668   scm_putc (' ', port);
1669   scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
1670   scm_putc ('>', port);
1671   return 1;
1672 }
1673
1674 void
1675 scm_ports_prehistory ()
1676 {
1677   scm_numptob = 0;
1678   scm_ptobs = (scm_t_ptob_descriptor *) scm_malloc (sizeof (scm_t_ptob_descriptor));
1679 }
1680
1681 \f
1682
1683 /* Void ports.   */
1684
1685 scm_t_bits scm_tc16_void_port = 0;
1686
1687 static int fill_input_void_port (SCM port SCM_UNUSED)
1688 {
1689   return EOF;
1690 }
1691
1692 static void
1693 write_void_port (SCM port SCM_UNUSED,
1694                  const void *data SCM_UNUSED,
1695                  size_t size SCM_UNUSED)
1696 {
1697 }
1698
1699 static SCM
1700 scm_i_void_port (long mode_bits)
1701 {
1702   scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
1703   {
1704     SCM answer = scm_new_port_table_entry (scm_tc16_void_port);
1705     scm_t_port * pt = SCM_PTAB_ENTRY(answer);
1706
1707     scm_port_non_buffer (pt);
1708   
1709     SCM_SETSTREAM (answer, 0);
1710     SCM_SET_CELL_TYPE (answer, scm_tc16_void_port | mode_bits);
1711     scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
1712     return answer;
1713   }
1714 }
1715
1716 SCM
1717 scm_void_port (char *mode_str)
1718 {
1719   return scm_i_void_port (scm_mode_bits (mode_str));
1720 }
1721
1722 SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1723             (SCM mode),
1724             "Create and return a new void port.  A void port acts like\n"
1725             "@file{/dev/null}.  The @var{mode} argument\n"
1726             "specifies the input/output modes for this port: see the\n"
1727             "documentation for @code{open-file} in @ref{File Ports}.")
1728 #define FUNC_NAME s_scm_sys_make_void_port
1729 {
1730   return scm_i_void_port (scm_i_mode_bits (mode));
1731 }
1732 #undef FUNC_NAME
1733
1734 \f
1735 /* Initialization.  */
1736
1737 void
1738 scm_init_ports ()
1739 {
1740   /* lseek() symbols.  */
1741   scm_c_define ("SEEK_SET", scm_from_int (SEEK_SET));
1742   scm_c_define ("SEEK_CUR", scm_from_int (SEEK_CUR));
1743   scm_c_define ("SEEK_END", scm_from_int (SEEK_END));
1744
1745   scm_tc16_void_port = scm_make_port_type ("void", fill_input_void_port, 
1746                                            write_void_port);
1747
1748   cur_inport_fluid = scm_permanent_object (scm_make_fluid ());
1749   cur_outport_fluid = scm_permanent_object (scm_make_fluid ());
1750   cur_errport_fluid = scm_permanent_object (scm_make_fluid ());
1751   cur_loadport_fluid = scm_permanent_object (scm_make_fluid ());
1752
1753 #include "libguile/ports.x"
1754 }
1755
1756 /*
1757   Local Variables:
1758   c-file-style: "gnu"
1759   End:
1760 */