Contents in 1999-06-04-13 of release-21-2.
[chise/xemacs-chise.git.1] / src / lstream.c
1 /* Generic stream implementation.
2    Copyright (C) 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Not in FSF. */
24
25 /* Written by Ben Wing. */
26
27 #include <config.h>
28 #include "lisp.h"
29 #include <limits.h>
30
31 #include "buffer.h"
32 #include "insdel.h"
33 #include "lstream.h"
34
35 #include "sysfile.h"
36 #include <errno.h>
37
38 /* This function provides a generic buffering stream implementation.
39    Conceptually, you send data to the stream or read data from the
40    stream, not caring what's on the other end of the stream.  The
41    other end could be another stream, a file descriptor, a stdio
42    stream, a fixed block of memory, a reallocating block of memory,
43    etc.  The main purpose of the stream is to provide a standard
44    interface and to do buffering.  Macros are defined to read
45    or write characters, so the calling functions do not have to
46    worry about blocking data together in order to achieve efficiency.
47    */
48
49 /* Note that this object is called "stream" in Lisp but "lstream"
50    in C.  The reason for this is that "stream" is too generic a name
51    for C; too much likelihood of conflict/confusion with C++, etc. */
52
53 /* Functions are as follows:
54
55 Lstream *Lstream_new (Lstream_implementation *imp, CONST char *mode)
56         Allocate and return a new Lstream.  This function is not
57         really meant to be called directly; rather, each stream type
58         should provide its own stream creation function, which
59         creates the stream and does any other necessary creation
60         stuff (e.g. opening a file).
61
62 void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
63                             int buffering_size)
64         Change the buffering of a stream.  See lstream.h.  By default
65         the buffering is STREAM_BLOCK_BUFFERED.
66
67 int Lstream_flush (Lstream *lstr)
68         Flush out any pending unwritten data in the stream.  Clear
69         any buffered input data.  Returns 0 on success, -1 on error.
70
71 int Lstream_putc (Lstream *stream, int c)
72         Write out one byte to the stream.  This is a macro and so
73         it is very efficient.  The C argument is only evaluated once
74         but the STREAM argument is evaluated more than once.  Returns
75         0 on success, -1 on error.
76
77 int Lstream_getc (Lstream *stream)
78         Read one byte from the stream.  This is a macro and so it
79         is very efficient.  The STREAM argument is evaluated more
80         than once.  Return value is -1 for EOF or error.
81
82 void Lstream_ungetc (Lstream *stream, int c)
83         Push one byte back onto the input queue.  This will be the
84         next byte read from the stream.  Any number of bytes can be
85         pushed back and will be read in the reverse order they were
86         pushed back -- most recent first. (This is necessary for
87         consistency -- if there are a number of bytes that have been
88         unread and I read and unread a byte, it needs to be the first
89         to be read again.) This is a macro and so it is very
90         efficient.  The C argument is only evaluated once but the
91         STREAM argument is evaluated more than once.
92
93 int Lstream_fputc (Lstream *stream, int c)
94 int Lstream_fgetc (Lstream *stream)
95 void Lstream_fungetc (Lstream *stream, int c)
96         Function equivalents of the above macros.
97
98 int Lstream_read (Lstream *stream, void *data, size_t size)
99         Read SIZE bytes of DATA from the stream.  Return the number of
100         bytes read.  0 means EOF. -1 means an error occurred and no
101         bytes were read.
102
103 int Lstream_write (Lstream *stream, void *data, size_t size)
104         Write SIZE bytes of DATA to the stream.  Return the number of
105         bytes written.  -1 means an error occurred and no bytes were
106         written.
107
108 void Lstream_unread (Lstream *stream, void *data, size_t size)
109         Push back SIZE bytes of DATA onto the input queue.  The
110         next call to Lstream_read() with the same size will read the
111         same bytes back.  Note that this will be the case even if
112         there is other pending unread data.
113
114 int Lstream_delete (Lstream *stream)
115         Frees all memory associated with the stream is freed.  Calling
116         this is not strictly necessary, but it is much more efficient
117         than having the Lstream be garbage-collected.
118
119 int Lstream_close (Lstream *stream)
120         Close the stream.  All data will be flushed out.
121
122 void Lstream_reopen (Lstream *stream)
123         Reopen a closed stream.  This enables I/O on it again.
124         This is not meant to be called except from a wrapper routine
125         that reinitializes variables and such -- the close routine
126         may well have freed some necessary storage structures, for
127         example.
128
129 void Lstream_rewind (Lstream *stream)
130         Rewind the stream to the beginning.
131 */
132
133 #define DEFAULT_BLOCK_BUFFERING_SIZE 512
134 #define MAX_READ_SIZE 512
135
136 static Lisp_Object
137 mark_lstream (Lisp_Object obj, void (*markobj) (Lisp_Object))
138 {
139   Lstream *lstr = XLSTREAM (obj);
140   return lstr->imp->marker ? (lstr->imp->marker) (obj, markobj) : Qnil;
141 }
142
143 static void
144 print_lstream (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
145 {
146   Lstream *lstr = XLSTREAM (obj);
147   char buf[200];
148
149   sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (%s lstream) 0x%lx>",
150            lstr->imp->name, (long) lstr);
151   write_c_string (buf, printcharfun);
152 }
153
154 static void
155 finalize_lstream (void *header, int for_disksave)
156 {
157   /* WARNING WARNING WARNING.  This function (and all finalize functions)
158      may get called more than once on the same object, and may get called
159      (at dump time) on objects that are not being released. */
160   Lstream *lstr = (Lstream *) header;
161
162 #if 0 /* this may cause weird Broken Pipes? */
163   if (for_disksave)
164     {
165       Lstream_pseudo_close (lstr);
166       return;
167     }
168 #endif
169   if (lstr->flags & LSTREAM_FL_IS_OPEN)
170     {
171       if (for_disksave)
172         {
173           if (lstr->flags & LSTREAM_FL_CLOSE_AT_DISKSAVE)
174             Lstream_close (lstr);
175         }
176       else
177         /* Just close. */
178         Lstream_close (lstr);
179     }
180 }
181
182 static size_t
183 sizeof_lstream (CONST void *header)
184 {
185   CONST Lstream *lstr = (CONST Lstream *) header;
186   return sizeof (*lstr) + lstr->imp->size - 1;
187 }
188
189 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("stream", lstream,
190                                         mark_lstream, print_lstream,
191                                         finalize_lstream, 0, 0,
192                                         sizeof_lstream, Lstream);
193 \f
194 void
195 Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
196                        int buffering_size)
197 {
198   lstr->buffering = buffering;
199   switch (buffering)
200     {
201     case LSTREAM_UNBUFFERED:
202       lstr->buffering_size = 0; break;
203     case LSTREAM_BLOCK_BUFFERED:
204       lstr->buffering_size = DEFAULT_BLOCK_BUFFERING_SIZE; break;
205     case LSTREAM_BLOCKN_BUFFERED:
206       lstr->buffering_size = buffering_size; break;
207     case LSTREAM_LINE_BUFFERED:
208     case LSTREAM_UNLIMITED:
209       lstr->buffering_size = INT_MAX; break;
210     }
211 }
212
213 static CONST Lstream_implementation *lstream_types[32];
214 static Lisp_Object Vlstream_free_list[32];
215 static int lstream_type_count;
216
217 Lstream *
218 Lstream_new (CONST Lstream_implementation *imp, CONST char *mode)
219 {
220   Lstream *p;
221   int i;
222
223   for (i = 0; i < lstream_type_count; i++)
224     {
225       if (lstream_types[i] == imp)
226         break;
227     }
228
229   if (i == lstream_type_count)
230     {
231       assert (lstream_type_count < countof (lstream_types));
232       lstream_types[lstream_type_count] = imp;
233       Vlstream_free_list[lstream_type_count] =
234         make_lcrecord_list (sizeof (*p) + imp->size - 1,
235                             &lrecord_lstream);
236       lstream_type_count++;
237     }
238
239   p = XLSTREAM (allocate_managed_lcrecord (Vlstream_free_list[i]));
240   /* Zero it out, except the header. */
241   memset ((char *) p + sizeof (p->header), 0,
242           sizeof (*p) - sizeof (p->header) + imp->size - 1);
243   p->imp = imp;
244   Lstream_set_buffering (p, LSTREAM_BLOCK_BUFFERED, 0);
245   p->flags = LSTREAM_FL_IS_OPEN;
246
247   /* convert mode (one of "r", "w", "rc", "wc") to p->flags */
248   assert (mode[0] == 'r' || mode[0] == 'w');
249   assert (mode[1] == 'c' || mode[1] == '\0');
250   p->flags |= (mode[0] == 'r' ? LSTREAM_FL_READ : LSTREAM_FL_WRITE);
251   if (mode[1] == 'c')
252     p->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
253
254   return p;
255 }
256
257 void
258 Lstream_set_character_mode (Lstream *lstr)
259 {
260   lstr->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
261 }
262
263 void
264 Lstream_delete (Lstream *lstr)
265 {
266   int i;
267   Lisp_Object val;
268
269   XSETLSTREAM (val, lstr);
270   for (i = 0; i < lstream_type_count; i++)
271     {
272       if (lstream_types[i] == lstr->imp)
273         {
274           free_managed_lcrecord (Vlstream_free_list[i], val);
275           return;
276         }
277     }
278
279   abort ();
280 }
281
282 #define Lstream_internal_error(reason, lstr) \
283   Lstream_signal_simple_error ("Internal error: " reason, lstr)
284
285 static void Lstream_signal_simple_error (CONST char *reason, Lstream *lstr)
286 {
287   Lisp_Object obj;
288   XSETLSTREAM (obj, lstr);
289   signal_simple_error (reason, obj);
290 }
291
292 void
293 Lstream_reopen (Lstream *lstr)
294 {
295   if (lstr->flags & LSTREAM_FL_IS_OPEN)
296     Lstream_internal_error ("lstream already open", lstr);
297   lstr->flags |= LSTREAM_FL_IS_OPEN;
298 }
299
300 /* Attempt to flush out all of the buffered data for writing. */
301
302 int
303 Lstream_flush_out (Lstream *lstr)
304 {
305   int num_written;
306
307   while (lstr->out_buffer_ind > 0)
308     {
309       int size = lstr->out_buffer_ind;
310       if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
311         Lstream_internal_error ("lstream not open", lstr);
312       if (! (lstr->flags & LSTREAM_FL_WRITE))
313         Lstream_internal_error ("lstream not open for writing", lstr);
314       if (!lstr->imp->writer)
315         Lstream_internal_error ("lstream has no writer", lstr);
316
317       if (lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
318         /* It's quite possible for us to get passed an incomplete
319            character at the end.  We need to spit back that
320            incomplete character. */
321         {
322           CONST unsigned char *data = lstr->out_buffer;
323           CONST unsigned char *dataend = data + size - 1;
324           assert (size > 0); /* safety check ... */
325           /* Optimize the most common case. */
326           if (!BYTE_ASCII_P (*dataend))
327             {
328               /* Go back to the beginning of the last (and possibly partial)
329                  character, and bump forward to see if the character is
330                  complete. */
331               VALIDATE_CHARPTR_BACKWARD (dataend);
332               if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != data + size)
333                 /* If not, chop the size down to ignore the last char
334                    and stash it away for next time. */
335                 size = dataend - data;
336               /* If we don't even have one character to write, then just
337                  skip out. */
338               if (size == 0)
339                 break;
340             }
341         }
342
343       num_written = (lstr->imp->writer) (lstr, lstr->out_buffer, size);
344       if (num_written == 0)
345         /* If nothing got written, then just hold the data.  This may
346            occur, for example, if this stream does non-blocking I/O;
347            the attempt to write the data might have resulted in an
348            EWOULDBLOCK error. */
349         return 0;
350       else if (num_written >= (int) lstr->out_buffer_ind)
351         lstr->out_buffer_ind = 0;
352       else if (num_written > 0)
353         {
354           memmove (lstr->out_buffer, lstr->out_buffer + num_written,
355                    lstr->out_buffer_ind - num_written);
356           lstr->out_buffer_ind -= num_written;
357         }
358       else
359         /* If error, just hold the data, for similar reasons as above. */
360         return -1;
361     }
362
363   if (lstr->imp->flusher)
364     return (lstr->imp->flusher) (lstr);
365
366   return 0;
367 }
368
369 int
370 Lstream_flush (Lstream *lstr)
371 {
372   if (Lstream_flush_out (lstr) < 0)
373     return -1;
374
375   /* clear out buffered data */
376   lstr->in_buffer_current = lstr->in_buffer_ind = 0;
377   lstr->unget_buffer_ind = 0;
378
379   return 0;
380 }
381
382 /* We want to add NUM characters.  This function ensures that the
383    buffer is large enough for this (per the buffering size specified
384    in the stream) and returns the number of characters we can
385    actually write.  If FORCE is set, ignore the buffering size
386    and go ahead and make space for all the chars even if it exceeds
387    the buffering size. (This is used to deal with the possibility
388    that the stream writer might refuse to write any bytes now, e.g.
389    if it's getting EWOULDBLOCK errors.   We have to keep stocking them
390    up until they can be written, so as to avoid losing data. */
391
392 static int
393 Lstream_adding (Lstream *lstr, size_t num, int force)
394 {
395   /* Compute the size that the outbuffer needs to be after the
396      chars are added. */
397   size_t size_needed = max (lstr->out_buffer_size,
398                             num + lstr->out_buffer_ind);
399   /* Maybe chop it down so that we don't buffer more characters
400      than our advertised buffering size. */
401   if (!force)
402     size_needed = min (lstr->buffering_size, size_needed);
403   DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size,
404               size_needed, unsigned char);
405   /* There might be more data buffered than the buffering size,
406      so make sure we don't return a negative number here. */
407   return max (0, min (num, size_needed - lstr->out_buffer_ind));
408 }
409
410 /* Like Lstream_write(), but does not handle line-buffering correctly. */
411
412 static int
413 Lstream_write_1 (Lstream *lstr, CONST void *data, size_t size)
414 {
415   CONST unsigned char *p = (CONST unsigned char *) data;
416   int off = 0;
417   if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
418     Lstream_internal_error ("lstream not open", lstr);
419   if (! (lstr->flags & LSTREAM_FL_WRITE))
420     Lstream_internal_error ("lstream not open for writing", lstr);
421   {
422     int couldnt_write_last_time = 0;
423
424     while (1)
425       {
426         /* Figure out how much we can add to the buffer */
427         int chunk = Lstream_adding (lstr, size, 0);
428         if (chunk == 0)
429           {
430             if (couldnt_write_last_time)
431               /* Ung, we ran out of space and tried to flush
432                  the buffer, but it didn't work because the stream
433                  writer is refusing to accept any data.  So we
434                  just have to squirrel away all the rest of the
435                  stuff. */
436               chunk = Lstream_adding (lstr, size, 1);
437             else
438               couldnt_write_last_time = 1;
439           }
440         /* Do it. */
441         if (chunk > 0)
442           {
443             memcpy (lstr->out_buffer + lstr->out_buffer_ind, p + off, chunk);
444             lstr->out_buffer_ind += chunk;
445             lstr->byte_count     += chunk;
446             size -= chunk;
447             off  += chunk;
448           }
449         /* If the buffer is full and we have more to add, flush it out. */
450         if (size > 0)
451           {
452             if (Lstream_flush_out (lstr) < 0)
453               {
454                 if (off == 0)
455                   return -1;
456                 else
457                   return off;
458               }
459           }
460         else
461           break;
462       }
463   }
464   return off;
465 }
466
467 /* If the stream is not line-buffered, then we can just call
468    Lstream_write_1(), which writes in chunks.  Otherwise, we
469    repeatedly call Lstream_putc(), which knows how to handle
470    line buffering. */
471
472 int
473 Lstream_write (Lstream *lstr, CONST void *data, size_t size)
474 {
475   int i;
476   CONST unsigned char *p = (CONST unsigned char *) data;
477
478   if (size == 0)
479     return size;
480   if (lstr->buffering != LSTREAM_LINE_BUFFERED)
481     return Lstream_write_1 (lstr, data, size);
482   for (i = 0; i < (int) size; i++)
483     {
484       if (Lstream_putc (lstr, p[i]) < 0)
485         break;
486     }
487   return i == 0 ? -1 : 0;
488 }
489
490 int
491 Lstream_was_blocked_p (Lstream *lstr)
492 {
493   if (lstr->imp->was_blocked_p)
494     return (lstr->imp->was_blocked_p) (lstr);
495   else
496     return 0;
497 }
498
499 static int
500 Lstream_raw_read (Lstream *lstr, unsigned char *buffer, size_t size)
501 {
502   if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
503     Lstream_internal_error ("lstream not open", lstr);
504   if (! (lstr->flags & LSTREAM_FL_READ))
505     Lstream_internal_error ("lstream not open for reading", lstr);
506   if (!lstr->imp->reader)
507     Lstream_internal_error ("lstream has no reader", lstr);
508
509   return (lstr->imp->reader) (lstr, buffer, size);
510 }
511
512 /* Assuming the buffer is empty, fill it up again. */
513
514 static int
515 Lstream_read_more (Lstream *lstr)
516 {
517 #if 0
518   int size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
519 #else
520   /* If someone requested a larger buffer size, so be it! */
521   int size_needed = max (1, lstr->buffering_size);
522 #endif
523   int size_gotten;
524
525   DO_REALLOC (lstr->in_buffer, lstr->in_buffer_size,
526               size_needed, unsigned char);
527   size_gotten = Lstream_raw_read (lstr, lstr->in_buffer, size_needed);
528   lstr->in_buffer_current = max (0, size_gotten);
529   lstr->in_buffer_ind = 0;
530   return size_gotten < 0 ? -1 : size_gotten;
531 }
532
533 int
534 Lstream_read (Lstream *lstr, void *data, size_t size)
535 {
536   unsigned char *p = (unsigned char *) data;
537   int off = 0;
538   size_t chunk;
539   int error_occurred = 0;
540
541   if (size == 0)
542     return 0;
543
544   /* First try to get some data from the unget buffer */
545   chunk = min (size, lstr->unget_buffer_ind);
546   if (chunk > 0)
547     {
548       /* The bytes come back in reverse order. */
549       for (; off < (int) chunk; off++)
550         p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
551       lstr->byte_count += chunk;
552       size -= chunk;
553     }
554
555   while (size > 0)
556     {
557       /* Take whatever we can from the in buffer */
558       chunk = min (size, lstr->in_buffer_current - lstr->in_buffer_ind);
559       if (chunk > 0)
560         {
561           memcpy (p + off, lstr->in_buffer + lstr->in_buffer_ind, chunk);
562           lstr->in_buffer_ind += chunk;
563           lstr->byte_count    += chunk;
564           size -= chunk;
565           off  += chunk;
566         }
567
568       /* If we need some more, try to get some more from the stream's end */
569       if (size > 0)
570         {
571           int retval = Lstream_read_more (lstr);
572           if (retval < 0)
573             error_occurred = 1;
574           if (retval <= 0)
575             break;
576         }
577     }
578
579   /* #### Beware of OFF ending up 0. */
580   if ((lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS) && off > 0)
581     {
582       /* It's quite possible for us to get passed an incomplete
583          character at the end.  We need to spit back that
584          incomplete character. */
585       CONST unsigned char *dataend = p + off - 1;
586       /* Optimize the most common case. */
587       if (!BYTE_ASCII_P (*dataend))
588         {
589           /* Go back to the beginning of the last (and possibly partial)
590              character, and bump forward to see if the character is
591              complete. */
592           VALIDATE_CHARPTR_BACKWARD (dataend);
593           if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != p + off)
594             {
595               int newoff = dataend - p;
596               /* If not, chop the size down to ignore the last char
597                  and stash it away for next time. */
598               Lstream_unread (lstr, dataend, off - newoff);
599               off = newoff;
600             }
601         }
602     }
603
604   return ((off == 0 && error_occurred) ? -1 : off);
605 }
606
607 void
608 Lstream_unread (Lstream *lstr, CONST void *data, size_t size)
609 {
610   int i;
611   unsigned char *p = (unsigned char *) data;
612
613   /* Make sure buffer is big enough */
614
615   DO_REALLOC (lstr->unget_buffer, lstr->unget_buffer_size,
616               lstr->unget_buffer_ind + size, unsigned char);
617
618   /* Bytes have to go on in reverse order -- they are reversed
619      again when read back. */
620   for (i = size - 1; i >= 0; i--)
621     lstr->unget_buffer[lstr->unget_buffer_ind++] = p[i];
622   lstr->byte_count -= size;
623 }
624
625 int
626 Lstream_rewind (Lstream *lstr)
627 {
628   if (!lstr->imp->rewinder)
629     Lstream_internal_error ("lstream has no rewinder", lstr);
630   if (Lstream_flush (lstr) < 0)
631     return -1;
632   lstr->byte_count = 0;
633   return (lstr->imp->rewinder) (lstr);
634 }
635
636 int
637 Lstream_seekable_p (Lstream *lstr)
638 {
639   if (!lstr->imp->rewinder)
640     return 0;
641   if (!lstr->imp->seekable_p)
642     return 1;
643   return (lstr->imp->seekable_p) (lstr);
644 }
645
646 static int
647 Lstream_pseudo_close (Lstream *lstr)
648 {
649   int rc;
650
651   if (!lstr->flags & LSTREAM_FL_IS_OPEN)
652     Lstream_internal_error ("lstream is not open", lstr);
653
654   /* don't check errors here -- best not to risk file descriptor loss */
655   rc = Lstream_flush (lstr);
656
657   return rc;
658 }
659
660 int
661 Lstream_close (Lstream *lstr)
662 {
663   int rc = 0;
664
665   if (lstr->flags & LSTREAM_FL_IS_OPEN)
666     {
667       rc = Lstream_pseudo_close (lstr);
668       /*
669        * We used to return immediately if the closer method reported
670        * failure, leaving the stream open.  But this is no good, for
671        * the following reasons.
672        *
673        * 1. The finalizer method used in GC makes no provision for
674        *    failure, so we must not return without freeing buffer
675        *    memory.
676        *
677        * 2. The closer method may have already freed some memory
678        *    used for I/O in this stream.  E.g. encoding_closer frees
679        *    ENCODING_STREAM_DATA(stream)->runoff.  If a writer method
680        *    tries to use this buffer later, it will write into memory
681        *    that may have been allocated elsewhere.  Sometime later
682        *    you will see a sign that says "Welcome to Crash City."
683        *
684        * 3. The closer can report failure if a flush fails in the
685        *    other stream in a MULE encoding/decoding stream pair.
686        *    The other stream in the pair is closed, but returning
687        *    early leaves the current stream open.  If we try to
688        *    flush the current stream later, we will crash when the
689        *    flusher notices that the other end stream is closed.
690        *
691        * So, we no longer abort the close if the closer method
692        * reports some kind of failure.  We still report the failure
693        * to the caller.
694        */
695       if (lstr->imp->closer)
696         if ((lstr->imp->closer) (lstr) < 0)
697           rc = -1;
698     }
699
700   lstr->flags &= ~LSTREAM_FL_IS_OPEN;
701   lstr->byte_count = 0;
702   /* Note that Lstream_flush() reset all the buffer indices.  That way,
703      the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
704      on a closed stream will call into the function equivalents, which will
705      cause an error. */
706
707   /* We set the pointers to 0 so that we don't lose when this function
708      is called more than once on the same object */
709   if (lstr->out_buffer)
710     {
711       xfree (lstr->out_buffer);
712       lstr->out_buffer = 0;
713     }
714   if (lstr->in_buffer)
715     {
716       xfree (lstr->in_buffer);
717       lstr->in_buffer = 0;
718     }
719   if (lstr->unget_buffer)
720     {
721       xfree (lstr->unget_buffer);
722       lstr->unget_buffer = 0;
723     }
724
725   return rc;
726 }
727
728 int
729 Lstream_fputc (Lstream *lstr, int c)
730 {
731   unsigned char ch = (unsigned char) c;
732   int retval = Lstream_write_1 (lstr, &ch, 1);
733   if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED && ch == '\n')
734     return Lstream_flush_out (lstr);
735   return retval < 0 ? -1 : 0;
736 }
737
738 int
739 Lstream_fgetc (Lstream *lstr)
740 {
741   unsigned char ch;
742   if (Lstream_read (lstr, &ch, 1) <= 0)
743     return -1;
744   return ch;
745 }
746
747 void
748 Lstream_fungetc (Lstream *lstr, int c)
749 {
750   unsigned char ch = (unsigned char) c;
751   Lstream_unread (lstr, &ch, 1);
752 }
753
754 \f
755 /************************ some stream implementations *********************/
756
757 /*********** a stdio stream ***********/
758
759 struct stdio_stream
760 {
761   FILE *file;
762   int closing;
763 };
764
765 #define STDIO_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, stdio)
766
767 DEFINE_LSTREAM_IMPLEMENTATION ("stdio", lstream_stdio,
768                                sizeof (struct stdio_stream));
769
770 static Lisp_Object
771 make_stdio_stream_1 (FILE *stream, int flags, CONST char *mode)
772 {
773   Lisp_Object obj;
774   Lstream *lstr = Lstream_new (lstream_stdio, mode);
775   struct stdio_stream *str = STDIO_STREAM_DATA (lstr);
776   str->file = stream;
777   str->closing = flags & LSTR_CLOSING;
778   lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
779   XSETLSTREAM (obj, lstr);
780   return obj;
781 }
782
783 Lisp_Object
784 make_stdio_input_stream (FILE *stream, int flags)
785 {
786   return make_stdio_stream_1 (stream, flags, "r");
787 }
788
789 Lisp_Object
790 make_stdio_output_stream (FILE *stream, int flags)
791 {
792   return make_stdio_stream_1 (stream, flags, "w");
793 }
794
795 static int
796 stdio_reader (Lstream *stream, unsigned char *data, size_t size)
797 {
798   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
799   size_t val = fread (data, 1, (size_t) size, str->file);
800   if (!val && ferror (str->file))
801     return -1;
802   return (int) val;
803 }
804
805 static int
806 stdio_writer (Lstream *stream, CONST unsigned char *data, size_t size)
807 {
808   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
809   size_t val = fwrite (data, 1, size, str->file);
810   if (!val && ferror (str->file))
811     return -1;
812   return (int) val;
813 }
814
815 static int
816 stdio_rewinder (Lstream *stream)
817 {
818   rewind (STDIO_STREAM_DATA (stream)->file);
819   return 0;
820 }
821
822 static int
823 stdio_seekable_p (Lstream *stream)
824 {
825   struct stat lestat;
826   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
827
828   if (fstat (fileno (str->file), &lestat) < 0)
829     return 0;
830   return S_ISREG (lestat.st_mode);
831 }
832
833 static int
834 stdio_flusher (Lstream *stream)
835 {
836   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
837   if (stream->flags & LSTREAM_FL_WRITE)
838     return fflush (str->file);
839   else
840     /* call fpurge?  Only exists on some systems.  #### Why not add a
841        configure check for HAVE_FPURGE and utilize it on systems that
842        support it?  --hniksic */
843     return 0;
844 }
845
846 static int
847 stdio_closer (Lstream *stream)
848 {
849   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
850   if (str->closing)
851     return fclose (str->file);
852   else
853   if (stream->flags & LSTREAM_FL_WRITE)
854     return fflush (str->file);
855   else
856     /* call fpurge?  Only exists on some systems. */
857     return 0;
858 }
859
860 /*********** a file descriptor ***********/
861
862 struct filedesc_stream
863 {
864   int fd;
865   int pty_max_bytes;
866   Bufbyte eof_char;
867   int starting_pos;
868   int current_pos;
869   int end_pos;
870   int chars_sans_newline;
871   unsigned int closing :1;
872   unsigned int allow_quit :1;
873   unsigned int blocked_ok :1;
874   unsigned int pty_flushing :1;
875   unsigned int blocking_error_p :1;
876 };
877
878 #define FILEDESC_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, filedesc)
879
880 DEFINE_LSTREAM_IMPLEMENTATION ("filedesc", lstream_filedesc,
881                                sizeof (struct filedesc_stream));
882
883 /* Make a stream that reads from or writes to a file descriptor FILEDESC.
884    OFFSET is the offset from the *current* file pointer that the reading
885    should start at.  COUNT is the number of bytes to be read (it is
886    ignored when writing); -1 for unlimited. */
887 static Lisp_Object
888 make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
889                         CONST char *mode)
890 {
891   Lisp_Object obj;
892   Lstream *lstr = Lstream_new (lstream_filedesc, mode);
893   struct filedesc_stream *fstr = FILEDESC_STREAM_DATA (lstr);
894   fstr->fd = filedesc;
895   fstr->closing      = !!(flags & LSTR_CLOSING);
896   fstr->allow_quit   = !!(flags & LSTR_ALLOW_QUIT);
897   fstr->blocked_ok   = !!(flags & LSTR_BLOCKED_OK);
898   fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
899   fstr->blocking_error_p = 0;
900   fstr->chars_sans_newline = 0;
901   fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
902   fstr->current_pos = max (fstr->starting_pos, 0);
903   if (count < 0)
904     fstr->end_pos = -1;
905   else
906     fstr->end_pos = fstr->starting_pos + count;
907   lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
908   XSETLSTREAM (obj, lstr);
909   return obj;
910 }
911
912 Lisp_Object
913 make_filedesc_input_stream (int filedesc, int offset, int count, int flags)
914 {
915   return make_filedesc_stream_1 (filedesc, offset, count, flags, "r");
916 }
917
918 Lisp_Object
919 make_filedesc_output_stream (int filedesc, int offset, int count, int flags)
920 {
921   return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
922 }
923
924 static int
925 filedesc_reader (Lstream *stream, unsigned char *data, size_t size)
926 {
927   int nread;
928   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
929   if (str->end_pos >= 0)
930     size = min (size, (size_t) (str->end_pos - str->current_pos));
931   nread = (str->allow_quit ? read_allowing_quit : read) (str->fd, data, size);
932   if (nread > 0)
933     str->current_pos += nread;
934   return nread;
935 }
936
937 static int
938 errno_would_block_p (int val)
939 {
940 #ifdef EWOULDBLOCK
941   if (val == EWOULDBLOCK)
942     return 1;
943 #endif
944 #ifdef EAGAIN
945   if (val == EAGAIN)
946     return 1;
947 #endif
948   return 0;
949 }
950
951 static int
952 filedesc_writer (Lstream *stream, CONST unsigned char *data, size_t size)
953 {
954   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
955   int retval;
956   int need_newline = 0;
957
958   /* This function would be simple if it were not for the blasted
959      PTY max-bytes stuff.  Why the hell can't they just have written
960      the PTY drivers right so this problem doesn't exist?
961
962      Maybe all the PTY crap here should be moved into another stream
963      that does nothing but periodically insert EOF's as necessary. */
964   if (str->pty_flushing)
965     {
966       /* To make life easy, only send out one line at the most. */
967       CONST unsigned char *ptr;
968
969       ptr = (CONST unsigned char *) memchr (data, '\n', size);
970       if (ptr)
971         need_newline = 1;
972       else
973         ptr = data + size;
974       if (ptr - data >= str->pty_max_bytes - str->chars_sans_newline)
975         {
976           ptr = data + str->pty_max_bytes - str->chars_sans_newline;
977           need_newline = 0;
978         }
979       size = ptr - data;
980     }
981
982   /**** start of non-PTY-crap ****/
983   if (size > 0)
984     retval = ((str->allow_quit ? write_allowing_quit : write)
985               (str->fd, data, size));
986   else
987     retval = 0;
988   if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
989     {
990       str->blocking_error_p = 1;
991       return 0;
992     }
993   str->blocking_error_p = 0;
994   if (retval < 0)
995     return retval;
996   /**** end non-PTY-crap ****/
997
998   if (str->pty_flushing)
999     {
1000       str->chars_sans_newline += retval;
1001       /* Note that a newline was not among the bytes written out.
1002          Add to the number of non-newline bytes written out,
1003          and flush with an EOF if necessary.  Be careful to
1004          keep track of write errors as we go along and look
1005          out for EWOULDBLOCK. */
1006       if (str->chars_sans_newline >= str->pty_max_bytes)
1007         {
1008           int retval2 = ((str->allow_quit ? write_allowing_quit : write)
1009                          (str->fd, &str->eof_char, 1));
1010           if (retval2 > 0)
1011             str->chars_sans_newline = 0;
1012           else if (retval2 < 0)
1013             {
1014               /* Error writing the EOF char.  If nothing got written,
1015                  then treat this as an error -- either return an error
1016                  condition or set the blocking-error flag. */
1017               if (retval == 0)
1018                 {
1019                   if (errno_would_block_p (errno) && str->blocked_ok)
1020                     {
1021                       str->blocking_error_p = 1;
1022                       return 0;
1023                     }
1024                   else
1025                     return retval2;
1026                 }
1027               else
1028                 return retval;
1029             }
1030         }
1031     }
1032
1033   /* The need_newline flag is necessary because otherwise when the
1034      first byte is a newline, we'd get stuck never writing anything
1035      in pty-flushing mode. */
1036   if (need_newline)
1037     {
1038       Bufbyte nl = '\n';
1039       int retval2 = ((str->allow_quit ? write_allowing_quit : write)
1040                      (str->fd, &nl, 1));
1041       if (retval2 > 0)
1042         {
1043           str->chars_sans_newline = 0;
1044           retval++;
1045         }
1046       else if (retval2 < 0)
1047         {
1048           /* Error writing the newline char.  If nothing got written,
1049              then treat this as an error -- either return an error
1050              condition or set the blocking-error flag. */
1051           if (retval == 0)
1052             {
1053               if (errno_would_block_p (errno) && str->blocked_ok)
1054                 {
1055                   str->blocking_error_p = 1;
1056                   return 0;
1057                 }
1058               else
1059                 return retval2;
1060             }
1061           else
1062             return retval;
1063         }
1064     }
1065
1066   return retval;
1067 }
1068
1069 static int
1070 filedesc_rewinder (Lstream *stream)
1071 {
1072   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1073   if (str->starting_pos < 0 ||
1074       lseek (FILEDESC_STREAM_DATA (stream)->fd, str->starting_pos,
1075              SEEK_SET) == -1)
1076     return -1;
1077   else
1078     {
1079       str->current_pos = str->starting_pos;
1080       return 0;
1081     }
1082 }
1083
1084 static int
1085 filedesc_seekable_p (Lstream *stream)
1086 {
1087   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1088   if (str->starting_pos < 0)
1089     return 0;
1090   else
1091     {
1092       struct stat lestat;
1093
1094       if (fstat (str->fd, &lestat) < 0)
1095         return 0;
1096       return S_ISREG (lestat.st_mode);
1097     }
1098 }
1099
1100 static int
1101 filedesc_closer (Lstream *stream)
1102 {
1103   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1104   if (str->closing)
1105     return close (str->fd);
1106   else
1107     return 0;
1108 }
1109
1110 static int
1111 filedesc_was_blocked_p (Lstream *stream)
1112 {
1113   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1114   return str->blocking_error_p;
1115 }
1116
1117 void
1118 filedesc_stream_set_pty_flushing (Lstream *stream, int pty_max_bytes,
1119                                   Bufbyte eof_char)
1120 {
1121   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1122   str->pty_max_bytes = pty_max_bytes;
1123   str->eof_char = eof_char;
1124   str->pty_flushing = 1;
1125 }
1126
1127 int
1128 filedesc_stream_fd (Lstream *stream)
1129 {
1130   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1131   return str->fd;
1132 }
1133
1134 /*********** read from a Lisp string ***********/
1135
1136 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1137
1138 struct lisp_string_stream
1139 {
1140   Lisp_Object obj;
1141   Bytecount init_offset;
1142   Bytecount offset, end;
1143 };
1144
1145 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-string", lstream_lisp_string,
1146                                sizeof (struct lisp_string_stream));
1147
1148 Lisp_Object
1149 make_lisp_string_input_stream (Lisp_Object string, Bytecount offset,
1150                                Bytecount len)
1151 {
1152   Lisp_Object obj;
1153   Lstream *lstr;
1154   struct lisp_string_stream *str;
1155
1156   CHECK_STRING (string);
1157   if (len < 0)
1158     len = XSTRING_LENGTH (string) - offset;
1159   assert (offset >= 0);
1160   assert (len >= 0);
1161   assert (offset + len <= XSTRING_LENGTH (string));
1162
1163   lstr = Lstream_new (lstream_lisp_string, "r");
1164   str = LISP_STRING_STREAM_DATA (lstr);
1165   str->offset = offset;
1166   str->end = offset + len;
1167   str->init_offset = offset;
1168   str->obj = string;
1169   XSETLSTREAM (obj, lstr);
1170   return obj;
1171 }
1172
1173 static int
1174 lisp_string_reader (Lstream *stream, unsigned char *data, size_t size)
1175 {
1176   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1177   /* Don't lose if the string shrank past us ... */
1178   Bytecount offset = min (str->offset, XSTRING_LENGTH (str->obj));
1179   Bufbyte *strstart = XSTRING_DATA (str->obj);
1180   Bufbyte *start = strstart + offset;
1181
1182   /* ... or if someone changed the string and we ended up in the
1183      middle of a character. */
1184   /* Being in the middle of a character is `normal' unless
1185      LSTREAM_NO_PARTIAL_CHARS - mrb */
1186   if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
1187     VALIDATE_CHARPTR_BACKWARD (start);
1188   offset = start - strstart;
1189   size = min (size, (size_t) (str->end - offset));
1190   memcpy (data, start, size);
1191   str->offset = offset + size;
1192   return size;
1193 }
1194
1195 static int
1196 lisp_string_rewinder (Lstream *stream)
1197 {
1198   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1199   int pos = str->init_offset;
1200   if (pos > str->end)
1201     pos = str->end;
1202   /* Don't lose if the string shrank past us ... */
1203   pos = min (pos, XSTRING_LENGTH (str->obj));
1204   /* ... or if someone changed the string and we ended up in the
1205      middle of a character. */
1206   {
1207     Bufbyte *strstart = XSTRING_DATA (str->obj);
1208     Bufbyte *start = strstart + pos;
1209     VALIDATE_CHARPTR_BACKWARD (start);
1210     pos = start - strstart;
1211   }
1212   str->offset = pos;
1213   return 0;
1214 }
1215
1216 static Lisp_Object
1217 lisp_string_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
1218 {
1219   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (XLSTREAM (stream));
1220   return str->obj;
1221 }
1222
1223 /*********** a fixed buffer ***********/
1224
1225 #define FIXED_BUFFER_STREAM_DATA(stream) \
1226   LSTREAM_TYPE_DATA (stream, fixed_buffer)
1227
1228 struct fixed_buffer_stream
1229 {
1230   CONST unsigned char *inbuf;
1231   unsigned char *outbuf;
1232   size_t size;
1233   size_t offset;
1234 };
1235
1236 DEFINE_LSTREAM_IMPLEMENTATION ("fixed-buffer", lstream_fixed_buffer,
1237                                sizeof (struct fixed_buffer_stream));
1238
1239 Lisp_Object
1240 make_fixed_buffer_input_stream (CONST unsigned char *buf, size_t size)
1241 {
1242   Lisp_Object obj;
1243   Lstream *lstr = Lstream_new (lstream_fixed_buffer, "r");
1244   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1245   str->inbuf = buf;
1246   str->size = size;
1247   XSETLSTREAM (obj, lstr);
1248   return obj;
1249 }
1250
1251 Lisp_Object
1252 make_fixed_buffer_output_stream (unsigned char *buf, size_t size)
1253 {
1254   Lisp_Object obj;
1255   Lstream *lstr = Lstream_new (lstream_fixed_buffer, "w");
1256   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1257   str->outbuf = buf;
1258   str->size = size;
1259   XSETLSTREAM (obj, lstr);
1260   return obj;
1261 }
1262
1263 static int
1264 fixed_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1265 {
1266   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1267   size = min (size, str->size - str->offset);
1268   memcpy (data, str->inbuf + str->offset, size);
1269   str->offset += size;
1270   return size;
1271 }
1272
1273 static int
1274 fixed_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1275 {
1276   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1277   if (str->offset == str->size)
1278     {
1279       /* If we're at the end, just throw away the data and pretend
1280          we wrote all of it.  If we return 0, then the lstream routines
1281          will try again and again to write it out. */
1282       return size;
1283     }
1284   size = min (size, str->size - str->offset);
1285   memcpy (str->outbuf + str->offset, data, size);
1286   str->offset += size;
1287   return size;
1288 }
1289
1290 static int
1291 fixed_buffer_rewinder (Lstream *stream)
1292 {
1293   FIXED_BUFFER_STREAM_DATA (stream)->offset = 0;
1294   return 0;
1295 }
1296
1297 CONST unsigned char *
1298 fixed_buffer_input_stream_ptr (Lstream *stream)
1299 {
1300   assert (stream->imp == lstream_fixed_buffer);
1301   return FIXED_BUFFER_STREAM_DATA (stream)->inbuf;
1302 }
1303
1304 unsigned char *
1305 fixed_buffer_output_stream_ptr (Lstream *stream)
1306 {
1307   assert (stream->imp == lstream_fixed_buffer);
1308   return FIXED_BUFFER_STREAM_DATA (stream)->outbuf;
1309 }
1310
1311 /*********** write to a resizing buffer ***********/
1312
1313 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1314   LSTREAM_TYPE_DATA (stream, resizing_buffer)
1315
1316 struct resizing_buffer_stream
1317 {
1318   unsigned char *buf;
1319   size_t allocked;
1320   int max_stored;
1321   int stored;
1322 };
1323
1324 DEFINE_LSTREAM_IMPLEMENTATION ("resizing-buffer", lstream_resizing_buffer,
1325                                sizeof (struct resizing_buffer_stream));
1326
1327 Lisp_Object
1328 make_resizing_buffer_output_stream (void)
1329 {
1330   Lisp_Object obj;
1331   XSETLSTREAM (obj, Lstream_new (lstream_resizing_buffer, "w"));
1332   return obj;
1333 }
1334
1335 static int
1336 resizing_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1337 {
1338   struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1339   DO_REALLOC (str->buf, str->allocked, str->stored + size, unsigned char);
1340   memcpy (str->buf + str->stored, data, size);
1341   str->stored += size;
1342   str->max_stored = max (str->max_stored, str->stored);
1343   return size;
1344 }
1345
1346 static int
1347 resizing_buffer_rewinder (Lstream *stream)
1348 {
1349   RESIZING_BUFFER_STREAM_DATA (stream)->stored = 0;
1350   return 0;
1351 }
1352
1353 static int
1354 resizing_buffer_closer (Lstream *stream)
1355 {
1356   struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1357   if (str->buf)
1358     {
1359       xfree (str->buf);
1360       str->buf = 0;
1361     }
1362   return 0;
1363 }
1364
1365 unsigned char *
1366 resizing_buffer_stream_ptr (Lstream *stream)
1367 {
1368   return RESIZING_BUFFER_STREAM_DATA (stream)->buf;
1369 }
1370
1371 /*********** write to an unsigned-char dynarr ***********/
1372
1373 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1374    but which is really just an unsigned_char_dynarr (e.g. its type
1375    is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1376
1377 #define DYNARR_STREAM_DATA(stream) \
1378   LSTREAM_TYPE_DATA (stream, dynarr)
1379
1380 struct dynarr_stream
1381 {
1382   unsigned_char_dynarr *dyn;
1383 };
1384
1385 DEFINE_LSTREAM_IMPLEMENTATION ("dynarr", lstream_dynarr,
1386                                sizeof (struct dynarr_stream));
1387
1388 Lisp_Object
1389 make_dynarr_output_stream (unsigned_char_dynarr *dyn)
1390 {
1391   Lisp_Object obj;
1392   XSETLSTREAM (obj, Lstream_new (lstream_dynarr, "w"));
1393   DYNARR_STREAM_DATA (XLSTREAM (obj))->dyn = dyn;
1394   return obj;
1395 }
1396
1397 static int
1398 dynarr_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1399 {
1400   struct dynarr_stream *str = DYNARR_STREAM_DATA (stream);
1401   Dynarr_add_many (str->dyn, data, size);
1402   return size;
1403 }
1404
1405 static int
1406 dynarr_rewinder (Lstream *stream)
1407 {
1408   Dynarr_reset (DYNARR_STREAM_DATA (stream)->dyn);
1409   return 0;
1410 }
1411
1412 static int
1413 dynarr_closer (Lstream *stream)
1414 {
1415   return 0;
1416 }
1417
1418 /************ read from or write to a Lisp buffer ************/
1419
1420 /* Note: Lisp-buffer read streams never return partial characters,
1421    and Lisp-buffer write streams expect to never get partial
1422    characters. */
1423
1424 #define LISP_BUFFER_STREAM_DATA(stream) \
1425   LSTREAM_TYPE_DATA (stream, lisp_buffer)
1426
1427 struct lisp_buffer_stream
1428 {
1429   Lisp_Object buffer;
1430   Lisp_Object orig_start;
1431   /* we use markers to properly deal with insertion/deletion */
1432   Lisp_Object start, end;
1433   int flags;
1434 };
1435
1436 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-buffer", lstream_lisp_buffer,
1437                                sizeof (struct lisp_buffer_stream));
1438
1439 static Lisp_Object
1440 make_lisp_buffer_stream_1 (struct buffer *buf, Bufpos start, Bufpos end,
1441                            int flags, CONST char *mode)
1442 {
1443   Lisp_Object obj;
1444   Lstream *lstr;
1445   struct lisp_buffer_stream *str;
1446   Bufpos bmin, bmax;
1447   int reading = !strcmp (mode, "r");
1448
1449   /* Make sure the luser didn't pass "w" in. */
1450   if (!strcmp (mode, "w"))
1451     abort ();
1452
1453   if (flags & LSTR_IGNORE_ACCESSIBLE)
1454     {
1455       bmin = BUF_BEG (buf);
1456       bmax = BUF_Z (buf);
1457     }
1458   else
1459     {
1460       bmin = BUF_BEGV (buf);
1461       bmax = BUF_ZV (buf);
1462     }
1463
1464   if (start == -1)
1465     start = bmin;
1466   if (end == -1)
1467     end = bmax;
1468   assert (bmin <= start);
1469   assert (start <= bmax);
1470   if (reading)
1471     {
1472       assert (bmin  <= end);
1473       assert (end   <= bmax);
1474       assert (start <= end);
1475     }
1476
1477   lstr = Lstream_new (lstream_lisp_buffer, mode);
1478   str = LISP_BUFFER_STREAM_DATA (lstr);
1479   {
1480     Lisp_Object marker;
1481     Lisp_Object buffer;
1482
1483     XSETBUFFER (buffer, buf);
1484     marker = Fmake_marker ();
1485     Fset_marker (marker, make_int (start), buffer);
1486     str->start = marker;
1487     marker = Fmake_marker ();
1488     Fset_marker (marker, make_int (start), buffer);
1489     str->orig_start = marker;
1490     if (reading)
1491       {
1492         marker = Fmake_marker ();
1493         Fset_marker (marker, make_int (end), buffer);
1494         str->end = marker;
1495       }
1496     else
1497       str->end = Qnil;
1498     str->buffer = buffer;
1499   }
1500   str->flags = flags;
1501   XSETLSTREAM (obj, lstr);
1502   return obj;
1503 }
1504
1505 Lisp_Object
1506 make_lisp_buffer_input_stream (struct buffer *buf, Bufpos start, Bufpos end,
1507                                int flags)
1508 {
1509   return make_lisp_buffer_stream_1 (buf, start, end, flags, "r");
1510 }
1511
1512 Lisp_Object
1513 make_lisp_buffer_output_stream (struct buffer *buf, Bufpos pos, int flags)
1514 {
1515   Lisp_Object lstr = make_lisp_buffer_stream_1 (buf, pos, 0, flags, "wc");
1516
1517   Lstream_set_character_mode (XLSTREAM (lstr));
1518   return lstr;
1519 }
1520
1521 static int
1522 lisp_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1523 {
1524   struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1525   unsigned char *orig_data = data;
1526   Bytind start;
1527   Bytind end;
1528   struct buffer *buf = XBUFFER (str->buffer);
1529
1530   if (!BUFFER_LIVE_P (buf))
1531     return 0; /* Fut. */
1532
1533   /* NOTE: We do all our operations in Bytind's.
1534      Keep in mind that SIZE is a value in bytes, not chars. */
1535
1536   start = bi_marker_position (str->start);
1537   end = bi_marker_position (str->end);
1538   if (!(str->flags & LSTR_IGNORE_ACCESSIBLE))
1539     {
1540       start = bytind_clip_to_bounds (BI_BUF_BEGV (buf), start,
1541                                      BI_BUF_ZV (buf));
1542       end = bytind_clip_to_bounds (BI_BUF_BEGV (buf), end,
1543                                    BI_BUF_ZV (buf));
1544     }
1545
1546   size = min (size, (size_t) (end - start));
1547   end = start + size;
1548   /* We cannot return a partial character. */
1549   VALIDATE_BYTIND_BACKWARD (buf, end);
1550
1551   while (start < end)
1552     {
1553       Bytind ceil;
1554       Bytecount chunk;
1555
1556       if (str->flags & LSTR_IGNORE_ACCESSIBLE)
1557         ceil = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE (buf, start);
1558       else
1559         ceil = BI_BUF_CEILING_OF (buf, start);
1560       chunk = min (ceil, end) - start;
1561       memcpy (data, BI_BUF_BYTE_ADDRESS (buf, start), chunk);
1562       data += chunk;
1563       start += chunk;
1564     }
1565
1566   if (EQ (buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE)
1567     {
1568       /* What a kludge.  What a kludge.  What a kludge. */
1569       unsigned char *p;
1570       for (p = orig_data; p < data; p++)
1571         if (*p == '\r')
1572           *p = '\n';
1573     }
1574
1575   set_bi_marker_position (str->start, end);
1576   return data - orig_data;
1577 }
1578
1579 static int
1580 lisp_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
1581 {
1582   struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1583   Bufpos pos;
1584   struct buffer *buf = XBUFFER (str->buffer);
1585
1586   if (!BUFFER_LIVE_P (buf))
1587     return 0; /* Fut. */
1588
1589   pos = marker_position (str->start);
1590   pos += buffer_insert_raw_string_1 (buf, pos, data, size, 0);
1591   set_marker_position (str->start, pos);
1592   return size;
1593 }
1594
1595 static int
1596 lisp_buffer_rewinder (Lstream *stream)
1597 {
1598   struct lisp_buffer_stream *str =
1599     LISP_BUFFER_STREAM_DATA (stream);
1600   struct buffer *buf = XBUFFER (str->buffer);
1601   long pos = marker_position (str->orig_start);
1602   if (!BUFFER_LIVE_P (buf))
1603     return -1; /* Fut. */
1604   if (pos > BUF_ZV (buf))
1605     pos = BUF_ZV (buf);
1606   if (pos < marker_position (str->orig_start))
1607     pos = marker_position (str->orig_start);
1608   if (MARKERP (str->end) && pos > marker_position (str->end))
1609     pos = marker_position (str->end);
1610   set_marker_position (str->start, pos);
1611   return 0;
1612 }
1613
1614 static Lisp_Object
1615 lisp_buffer_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
1616 {
1617   struct lisp_buffer_stream *str =
1618     LISP_BUFFER_STREAM_DATA (XLSTREAM (stream));
1619
1620   markobj (str->start);
1621   markobj (str->end);
1622   return str->buffer;
1623 }
1624
1625 Bufpos
1626 lisp_buffer_stream_startpos (Lstream *stream)
1627 {
1628   return marker_position (LISP_BUFFER_STREAM_DATA (stream)->start);
1629 }
1630
1631 \f
1632 /************************************************************************/
1633 /*                            initialization                            */
1634 /************************************************************************/
1635
1636 void
1637 lstream_type_create (void)
1638 {
1639   LSTREAM_HAS_METHOD (stdio, reader);
1640   LSTREAM_HAS_METHOD (stdio, writer);
1641   LSTREAM_HAS_METHOD (stdio, rewinder);
1642   LSTREAM_HAS_METHOD (stdio, seekable_p);
1643   LSTREAM_HAS_METHOD (stdio, flusher);
1644   LSTREAM_HAS_METHOD (stdio, closer);
1645
1646   LSTREAM_HAS_METHOD (filedesc, reader);
1647   LSTREAM_HAS_METHOD (filedesc, writer);
1648   LSTREAM_HAS_METHOD (filedesc, was_blocked_p);
1649   LSTREAM_HAS_METHOD (filedesc, rewinder);
1650   LSTREAM_HAS_METHOD (filedesc, seekable_p);
1651   LSTREAM_HAS_METHOD (filedesc, closer);
1652
1653   LSTREAM_HAS_METHOD (lisp_string, reader);
1654   LSTREAM_HAS_METHOD (lisp_string, rewinder);
1655   LSTREAM_HAS_METHOD (lisp_string, marker);
1656
1657   LSTREAM_HAS_METHOD (fixed_buffer, reader);
1658   LSTREAM_HAS_METHOD (fixed_buffer, writer);
1659   LSTREAM_HAS_METHOD (fixed_buffer, rewinder);
1660
1661   LSTREAM_HAS_METHOD (resizing_buffer, writer);
1662   LSTREAM_HAS_METHOD (resizing_buffer, rewinder);
1663   LSTREAM_HAS_METHOD (resizing_buffer, closer);
1664
1665   LSTREAM_HAS_METHOD (dynarr, writer);
1666   LSTREAM_HAS_METHOD (dynarr, rewinder);
1667   LSTREAM_HAS_METHOD (dynarr, closer);
1668
1669   LSTREAM_HAS_METHOD (lisp_buffer, reader);
1670   LSTREAM_HAS_METHOD (lisp_buffer, writer);
1671   LSTREAM_HAS_METHOD (lisp_buffer, rewinder);
1672   LSTREAM_HAS_METHOD (lisp_buffer, marker);
1673 }
1674
1675 void
1676 vars_of_lstream (void)
1677 {
1678   int i;
1679
1680   for (i = 0; i < countof (Vlstream_free_list); i++)
1681     {
1682       Vlstream_free_list[i] = Qnil;
1683       staticpro (&Vlstream_free_list[i]);
1684     }
1685 }